aquí es otra forma que acabo de descubrir: compruebe si el primer (y único) argumento para su decorador es invocable; si es así, has terminado y puedes devolver tu método de envoltura modificadora de comportamiento (decorado con functools.wraps
para preservar el nombre y la cadena de documentación).
en el otro caso, uno o más argumentos nombrados o posicionales deberían estar presentes; puede recopilar esos argumentos y devolver un invocable que acepte un primer argumento invocable y devuelva un método de envoltura, y dado que esa descripción se ajusta a la descripción del método de decorador, ¡devuelva ese mismo método de decorador! He usado functools.partial
aquí para obtener una versión de mi decorador, is_global_method
(que estoy trabajando en este momento; su implementación es, por supuesto, absurda, como se muestra a continuación, esto es solo para demostrar que la decoración funciona).
esta solución parece funcionar, pero seguro necesita más pruebas. si quieses nuestros ojos, puedes ver que el truco es solo tres o cuatro líneas como un patrón para recordar. ahora me pregunto si puedo incluir ese tipo de funcionalidad en otro decorador. ah, la metaness de eso!
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))
decorador de casa: http://pypi.python.org/pypi/decorator/ –