Hi,
in
def f1(aFunc):
def DecoratedWrapper(*args,**kwargs):
print(kwargs)
val = aFunc(*args,**kwargs)
print('Finished','\n')
return val
return DecoratedWrapper
@f1
def f(a,b=9):
print(a,b)
@f1
def add(x,y):
return x + y
f('Hello')
print(add(5,3))
The line 3 print(kwargs)
print nothing !?
who can I get the args and kwargs of the decorated function within DecoratedWrapper
?
Thanks.
Rosuav
(Chris Angelico)
June 12, 2024, 12:28pm
2
What you passed were positional arguments, not keyword. If you want them to be passed as keyword arguments, you would write it like this:
print(add(a=5, b=3))
2 Likes
effigies
(Chris Markiewicz)
June 12, 2024, 12:28pm
3
You passed your arguments as positional, not keyword:
In [3]: f('Hello')
...:
...: print(add(5,3))
{}
Hello 9
Finished
{}
Finished
8
If you pass as keyword args:
In [4]: f(a='Hello')
...:
...: print(add(x=5,y=3))
{'a': 'Hello'}
Hello 9
Finished
{'x': 5, 'y': 3}
Finished
8
You could write some code with inspect.signature
to convert args
and kwargs
into a dict of parameters-to-values as if you got only kwargs, but it won’t happen by itself.
1 Like
Thanks !!
and why when I’m doing
def f1(aFunc):
def DecoratedWrapper(**kwargs):
print(kwargs)
val = aFunc(**kwargs)
print('Finished','\n')
return val
return DecoratedWrapper
@f1
def f(a='Vaneloppe'):
print(a)
f()
I got
{}
Vaneloppe
Finished
why the line 3 give me an empty dict
?
but line 4 the aFunc took it…
effigies
(Chris Markiewicz)
June 12, 2024, 1:34pm
5
You have a default parameter a
for f
. What’s happening is:
def f(a='Vaneloppe'):
print(a)
_f = f # Keeping a reference around
f = f1(f) # f = f1.DecoratedWrapper where aFunc == _f
Then when you call f()
, DecoratedWrapper()
is called with no arguments, so print(kwargs)
prints {}
. Then _f()
is called. Because it has a default argument for a
, print(a)
prints that default.
It might help to add a little audit function that can show you the current function and the variables available to it:
import inspect
def audit():
calling_frame = inspect.currentframe().f_back
print(f'DBG: {calling_frame.f_code.co_name}: {calling_frame.f_locals}')
Then you drop this in your functions so you can see when and how each is called:
In [14]: def f1(aFunc):
...: audit()
...: def DecoratedWrapper(**kwargs):
...: audit()
...: print(kwargs)
...: val = aFunc(**kwargs)
...: print('Finished','\n')
...: return val
...: return DecoratedWrapper
...:
...: @f1
...: def f(a='Vaneloppe'):
...: audit()
...: print(a)
...:
DBG: f1: {'aFunc': <function f at 0x7889d8793e20>}
In [15]: f()
DBG: DecoratedWrapper: {'kwargs': {}, 'aFunc': <function f at 0x7889d8793e20>}
{}
DBG: f: {'a': 'Vaneloppe'}
Vaneloppe
Finished
f1()
is called during function definition, then when you call f()
, you call DecoratedWrapper
and then your original f()
function.
1 Like
Thank you @effigies ,
The
import inspect
def audit():
calling_frame = inspect.currentframe().f_back
print(f'DBG: {calling_frame.f_code.co_name}: {calling_frame.f_locals}')
Was really useful !..
1 Like
Hi,
a good way to remember:
args --> arguments
kwargs --> keyword arguments
that is, k = key, and w = word