I am trying to implement a decorator with *args and having a few problems.
As can be seen in examples number 3 and 5, when I pass *args to the decorator the first argument is not the function (which is what I intended it to be).
My code:
from functools import partial, wraps
def decorator(func=None, *_args, **_kwargs):
print('A:', func, _args, _kwargs)
if not func:
return partial(decorator, *_args, **_kwargs)
@wraps(func)
def wrapper(*args, **kwargs):
print('B:', func, args, kwargs, _args, _kwargs)
result = func(*args, **kwargs)
print('D:', func, args, kwargs, _args, _kwargs)
return result
return wrapper
Testing func1:
@decorator
def func1(*args, **kwargs):
print('C:', args, kwargs)
func1(10, 20, 30, x=40, y=50, z=60)
# Output:
# A: <function func1 at 0x7fc44e0a7ca0> () {}
# B: <function func1 at 0x7fc44e0a7ca0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {}
# C: (10, 20, 30) {'x': 40, 'y': 50, 'z': 60}
# D: <function func1 at 0x7fc44e0a7ca0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {}
Testing func2:
@decorator()
def func2(*args, **kwargs):
print('C:', args, kwargs)
func2(10, 20, 30, x=40, y=50, z=60)
# Output:
# A: None () {}
# A: <function func2 at 0x7fc44e0a79d0> () {}
# B: <function func2 at 0x7fc44e0a79d0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {}
# C: (10, 20, 30) {'x': 40, 'y': 50, 'z': 60}
# D: <function func2 at 0x7fc44e0a79d0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {}
Testing func3:
@decorator(1, 2, 3)
def func3(*args, **kwargs):
print('C', args, kwargs)
func3(10, 20, 30, x=40, y=50, z=60)
# Output:
# A: 1 (2, 3) {}
# B: 1 (<function func3 at 0x7fc44e001af0>,) {} (2, 3) {}
# TypeError: 'int' object is not callable
Testing func4:
@decorator(a=1, b=2, c=3)
def func4(*args, **kwargs):
print('C:', args, kwargs)
func4(10, 20, 30, x=40, y=50, z=60)
# Output:
# A: None () {'a': 1, 'b': 2, 'c': 3}
# A: <function func4 at 0x7fc44e0015e0> () {'a': 1, 'b': 2, 'c': 3}
# B: <function func4 at 0x7fc44e0015e0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {'a': 1, 'b': 2, 'c': 3}
# C: (10, 20, 30) {'x': 40, 'y': 50, 'z': 60}
# D: <function func4 at 0x7fc44e0015e0> (10, 20, 30) {'x': 40, 'y': 50, 'z': 60} () {'a': 1, 'b': 2, 'c': 3}
Testing func5
@decorator(1, 2, 3, a=1, b=2, c=3)
def func5(*args, **kwargs):
print('C:', args, kwargs)
func5(10, 20, 30, x=40, y=50, z=60)
# Output:
# A: 1 (2, 3) {'a': 1, 'b': 2, 'c': 3}
# B: 1 (<function func5 at 0x7fc44e0014c0>,) {} (2, 3) {'a': 1, 'b': 2, 'c': 3}
# TypeError: 'int' object is not callable