qui è un altro modo che ho appena scoperto: controlla se il primo (e unico) argomento del tuo decoratore è callable; se è così, hai finito e puoi restituire il tuo metodo di modifica del comportamento (a sua volta decorato con functools.wraps
per preservare il nome e la stringa di documentazione).
nell'altro caso, devono essere presenti uno o più argomenti denominati o posizionali; puoi raccogliere quegli argomenti e restituire un callable che accetta un callable come primo argomento e restituisce un metodo wrapper, e poiché quella descrizione si adatta alla descrizione del metodo decoratore, restituisci il metodo stesso decoratore! ho usato functools.partial
qui per ottenere una versione del mio decoratore, is_global_method
(che sto lavorando proprio ora - la sua implementazione è ovviamente senza senso come mostrato di seguito, questo è solo per dimostrare le opere di decorazione).
questa soluzione sembra funzionare ma sicuramente richiede più test. se ti trapani gli occhi, puoi vedere che il trucco è solo tre o quattro linee come schema da ricordare. ora mi chiedo se posso avvolgere questo tipo di funzionalità in un altro decoratore? ah, la mancanza di esso!
from functools import wraps
from functools import partial
_ = print
is_instance_of = isinstance
is_callable = lambda x: hasattr(x, '__call__')
def is_global_method(x, *, name = None):
if is_callable(x):
@wraps(x)
def wrapper(*P, **Q):
return { 'name': name, 'result': x(*P, **Q), }
return wrapper
# assert is_instance_of(x, str) # could do some sanity checks here
return partial(is_global_method, name = x)
@is_global_method
def f(x):
"""This is method f."""
return x ** 2
@is_global_method('foobar')
def g(x):
"""This is method g."""
return x ** 2
_(f.__name__)
_(f.__doc__)
_(f(42))
_(g.__name__)
_(g.__doc__)
_(g(42))
home decoratore: http://pypi.python.org/pypi/decorator/ –