Functions, **kwargs

Function object

my_func.__defaults__
my_func.__name__
my_func.__doc__

Arguments in functions

Arguments may be passed to a Python function either by position or explicitly by keyword.

For readability and performance, it makes sense to restrict the way arguments can be passed so that a developer need only look at the function definition to determine if items are passed by position, by position or keyword, or by keyword.

Order of arguments:

image

5 Types of arguments

  1. default arguments/parameters evaluated once during function definition, not on every function call
  2. positional arguments calling function based on order/position
  3. keyword arguments calling function using arguments names
  4. arbitrary positional arguments using * — unpacking iterables, it is a tuple
  5. arbitrary keyword arguments using ** — unpacking dict

Examples

# Example 1
def my_func(*args, **kwargs):
	return args, kwargs

my_func(1, 2, 3) # ((1, 2, 3), {})
my_func(*[1, 2, 3]) # ((1, 2, 3), {})
my_func({'arg': 45}) # (({'arg': 45},), {})
my_func(1, 2, 3, a=4, b=5) # ((1, 2, 3), {'a': 4, 'b': 5})
my_func(**{'arg': 56}) # ((), {'arg': 56})

The correct order of parameters

def pos_only_arg(arg, /):
    print(arg)

def kwd_only_arg(*, arg):
    print(arg)

def combined_example(pos_only, /, standard, *, kwd_only):
    print("p", pos_only, "s", standard, "k", kwd_only)

combined_example(1, 2, kwd_only=3) # p 1 s 2 k 3
combined_example(1, standard=2, kwd_only=3) # p 1 s 2 k 3
# Real-world Example: Avoiding **kwargs collisions
def format_data(data, /, **kwargs):
    pass

format_data({"a": 1}, data="some string") # Works! No ambiguity about `data`.
def func(positional, only, here, /, either, pos, or_, keyword, *, just, keywords, default="Alex", **kwargs):
    # We can only use one *
		pass

func(1, 2, 3, 4, 5, or_=6, keywords=7, just=8, default="Rustam", **{"a": 1, "l": 3})
image
def recv(maxsize, *, block): 
    'Receives a message' 
    pass

recv(1024, True) # TypeError, only 1 positional arg.
recv(1024, block=True) # Ok

Why they are useful? If you want to call another function with the same arguments.

def forwarder(*args, **kwargs):
		return f(*args, **kwargs)

Resources

SuperMade with Super