Reputation: 33
I am trying to test the utility of decorators in Python. When I write the following codes, there is an error:
TypeError: fizz_buzz_or_number() takes 1 positional argument but 2 were given
I first define a function log_calls(fn)
as
def log_calls(fn):
''' Wraps fn in a function named "inner" that writes
the arguments and return value to logfile.log '''
def inner(*args, **kwargs):
# Call the function with the received arguments and
# keyword arguments, storing the return value
out = fn(args, kwargs)
# Write a line with the function name, its
# arguments, and its return value to the log file
with open('logfile.log', 'a') as logfile:
logfile.write(
'%s called with args %s and kwargs %s, returning %s\n' %
(fn.__name__, args, kwargs, out))
# Return the return value
return out
return inner
After that, I use log_calls to decorate another function as:
@log_calls
def fizz_buzz_or_number(i):
''' Return "fizz" if i is divisible by 3, "buzz" if by
5, and "fizzbuzz" if both; otherwise, return i. '''
if i % 15 == 0:
return 'fizzbuzz'
elif i % 3 == 0:
return 'fizz'
elif i % 5 == 0:
return 'buzz'
else:
return i
When I run the following code
for i in range(1, 31):
print(fizz_buzz_or_number(i))
The error TypeError: fizz_buzz_or_number() takes 1 positional argument but 2 were given
comes.
I don't know what is wrong with this decorator, and how to fix this.
Upvotes: 3
Views: 7379
Reputation: 1121744
You are passing in 2 arguments to your decorated function here:
out = fn(args, kwargs)
If you wanted to apply the args
tuple and kwargs
dictionary as variable arguments, echo the function signature syntax, so use *
and **
again:
out = fn(*args, **kwargs)
See the Call expressions reference documentation:
If the syntax
*expression
appears in the function call, expression must evaluate to an iterable. Elements from these iterables are treated as if they were additional positional arguments.[...]
If the syntax
**expression
appears in the function call, expression must evaluate to a mapping, the contents of which are treated as additional keyword arguments.
Upvotes: 4