2017-03-03 1 views
0

J'essaye de tester l'utilité des décorateurs en Python. Lorsque j'écrire les codes suivants, il y a une erreur:Python decorator: TypeError: la fonction prend 1 argument positionnel mais 2 ont été donnés

TypeError: fizz_buzz_or_number() takes 1 positional argument but 2 were given 

Je définis première fonction log_calls(fn) comme

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 

Après cela, j'utilise log_calls pour décorer une autre fonction en tant que:

@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 

Lorsque j'exécute le code suivant

for i in range(1, 31): 
    print(fizz_buzz_or_number(i)) 

L'erreur TypeError: fizz_buzz_or_number() takes 1 positional argument but 2 were given vient.

Je ne sais pas quel est le problème avec ce décorateur, et comment résoudre ce problème.

Répondre

0

Vous passez dans 2 arguments à votre ici fonction décorée:

out = fn(args, kwargs) 

Si vous voulez appliquer la args tuple et kwargs dictionnaire comme arguments variables, font écho à la syntaxe de la signature de la fonction, utilisez donc à nouveau * et ** :

out = fn(*args, **kwargs) 

Voir la 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.

+0

Je vois ce que vous voulez dire. J'ai réessayé selon ta suggestion, ça marche maintenant. Merci beaucoup. – Luhuimiaomiao