2015-04-28 14 views
11
def decorated(f): 
    @functools.wraps(f) 
    def wrapper(): 
     return f() 
    return wrapper 

@decorated 
def g(): 
    pass 

functools.wraps fa il suo lavoro a preservare il nome della g:La funzione decorata usando functools.wraps solleva TypeError con il nome del wrapper. Perché? Come evitare?

>>> g.__name__ 
'g' 

Ma se mi passa un argomento per g, ho un TypeError contenente il nome della confezione:

>>> g(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: wrapper() takes no arguments (1 given) 

Da dove viene questo nome? Dove è conservato? E c'è un modo per rendere l'eccezione simile a g() takes no arguments?

+2

Correlati: http://stackoverflow.com/q/29488327/3001761 – jonrsharpe

risposta

8

Il nome deriva dall'oggetto codice; sia la funzione e il codice oggetto (che contiene il bytecode da eseguire, tra gli altri) contengono quel nome:

>>> g.__name__ 
'g' 
>>> g.__code__.co_name 
'wrapper' 

L'attributo del codice oggetto è di sola lettura:

>>> g.__code__.co_name = 'g' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: readonly attribute 

Faresti devo creare un nuovo oggetto codice per rinominarlo, vedi a previous answer of mine dove ho definito una funzione per farlo; usando la funzione rename_code_object() sulla vostra funzione decorato:

>>> g = rename_code_object(g, 'g') 
>>> g(1) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: g() takes no arguments (1 given) 

Si noti, tuttavia, che questo sarà tutto ciò che maschera codice era in esecuzione! Generalmente vuoi vedere che è stato coinvolto un wrapper decoratore; è il wrapper che lancia l'eccezione, non la funzione originale, dopotutto.

+0

In effetti ho appena collegato ad un'altra tua risposta in cui mostri come fare proprio questo! Dopo 'g = rename_code_object (g, 'g')', il messaggio di errore diventa 'TypeError: g() non accetta argomenti (1 dato)' come desiderato. – jonrsharpe

Problemi correlati