Reputation: 1201
I am trying to understand python decorator in depth
def lol(func):
def wrapper(*args,**kwargs):
print(*args)
print(**kwargs)
return func(*args,**kwargs)
return wrapper
@lol
def greet(name,lol,l):
return f'{name}:{lol}:{l}'
greet('tom',"dick",l="harry")
so when i give only positional args like greet('tom',"dick","harry")
this function works but when i give keyword arguments followed by positional argument greet('tom',"dick",l="harry")
it gives me error.
TypeError: 'l' is an invalid keyword argument for this function
but when i re-write my decorator like this
def lol(func):
def wrapper(*args,**kwargs):
print(*args)
print(**kwargs)
return wrapper(*args,**kwargs)
return func
It works fine. I am little confused what is happening. Would be great if somebody explains it no matter how silly is the cause. Thank you.
Upvotes: 1
Views: 83
Reputation: 155418
You don't want to do:
print(**kwargs)
That tries to expand the keyword arguments as keyword arguments to print
, so in your use case, it's like you typed print(l="harry")
, which is clearly nonsensical (print
doesn't take an argument named l
). Just do:
print(kwargs)
to see the dict
of keyword arguments received. Similarly, print(args)
is likely to be a better solution than print(*args)
as it will print repr
s, which typically tell you more about the arguments for debugging purposes.
The reason your second approach "works fine" is that it doesn't decorate anything. You make wrapper
, throw it away, then return the original func
, so the original func
is called, and print(**kwargs)
never occurs.
Upvotes: 1