I cannot really tell how to use *args and **kwargs when combined with decorators and default arguments. Let me give you a MWE.
def outer(f):
def inner(*args, **kwargs):
print("args:", args)
print("kwargs:", kwargs)
return inner
@outer
def simple(x, y):
pass
Running the simple
function passing arguments in a different format. So:
Running:
simple(10, 20)
args: (10, 20)
kwargs: {}
Running:
simple(x=10, y=20)
args: ()
kwargs: {'x': 10, 'y': 20}
Running:
simple(10, y=20)
args: (10,)
kwargs: {'y': 20}
All of these seem to be expected. What I cannot understand is if I define the simple
function with a default value something like:
@outer
def simple(x, y=100):
pass
If I then run simple(10)
I would have expected the outcome to be:
args: (10,)
kwargs: {'y': 100}
but I get
args: (10,)
kwargs: {}
instead. Probably my understanding is not that good, so how could I achieve the expected result?
In this case **kwargs
is not about the function signature, it's about how you called it.
And your call
simple(10)
have only specified one positional argument.
Decorator (wrapper) knows nothing about the function and its default arguments. It just passes the arguments it received further.
simple(*(10,), **{})
If you want to do some excercise and write decorator that is informed about the defaults of a function it is wrapping, I suggest to take a look at inspect.signature()
.