This example is taken from Beazley, Python Essential Reference 4e,
pg:101.
How is he doing:
func(*args, **kwargs)
where ‘func’ is the square-function which takes 1 argument. Earlier in
the chapter he sqawks about how the position and number of arguments
must match in a call/definition or a TypeError would be raised.
Also,
@trace
def square(x):
...
square = trace(square)
trace returns ‘callf’ so this is equivalent to writing: square = callf
which is fine because since square refers to a new-function-object, you can
call it with *args, **kwargs. But, then in callf he does func(*args...
Given that we just made ‘square’ refer to some other object, how is
the original square accessible inside? What mechanism is coming into
play?
@trace
def square(x):
return x*x
enable_tracing = True
if enable_tracing:
debug_log = open("debug.log","w")
def trace(func):
if enable_tracing:
def callf(*args,**kwargs):
debug_log.write("Calling %s: %s, %s\n" %
(func.__name__, args, kwargs))
r = func(*args,**kwargs) #????????
debug_log.write("%s returned %s\n" % (func.__name, r))
return r
return callf
else:
return func
The *-prefix means, “Use this sequence of values as the positional parameters to the function.” The **-prefix means, “Use this dictionary as the named parameters to the function.” If the sequence is empty, then no positional parameters are passed. If the dictionary is empty, then no named parameters are passed.
When you define a function with those prefixes, then the unaccounted for positional parameters go into the *-prefixed argument, and the unaccounted for named parameters go into the **-prefixed argument. So if you define a function like this:
then the function can be invoked with any arguments whatsoever. If that function then calls another function with those arguments, then it will be called however the wrapper was called.
Note that you can call a function with
(*args, **kwargs)even if wasn’t defined that way:Because kwargs is empty, there are no named parameters passed to the function. It gets only the one positional arguments in args.