2010-06-06 7 views
11

Si hago lo siguienteCopiar firma llamada al decorador

def mydecorator(f): 
    def wrapper(*args, **kwargs): 
     f(*args, **kwargs) 
    wrapper.__doc__ = f.__doc__ 
    wrapper.__name__ = f.__name__ 
    return wrapper 

@mydecorator 
def myfunction(a,b,c): 
    '''My docstring''' 
    pass 

Y a continuación, escriba help myfunction, me sale:

Help on function myfunction in module __main__: 

myfunction(*args, **kwargs) 
    My docstring 

Así que el nombre y la cadena de documentación se copian correctamente terminado. ¿Hay alguna forma de copiar también la firma de llamada real, en este caso (a, b, c)?

Respuesta

9

Aquí hay un ejemplo usando de decorator module Michele Simionato para fijar la firma:

import decorator 

@decorator.decorator 
def mydecorator(f,*args, **kwargs): 
    return f(*args, **kwargs) 

@mydecorator 
def myfunction(a,b,c): 
    '''My docstring''' 
    pass 

help(myfunction) 
# Help on function myfunction in module __main__: 

# myfunction(a, b, c) 
#  My docstring 
+0

Esta es una buena respuesta, pero crea una dependencia en otro tercero no oficial. ¿Hay una manera simple de hacer esto sin usar el módulo decorador? –

+0

El módulo 'decorator' es un único archivo que consta de <250 líneas. No creo que ripear las partes relevantes te ahorrará mucho código. La forma más fácil es instalar el módulo decorador. Tenga en cuenta que si no puede instalarlo en todo el sistema, siempre puede guardar una copia local de 'decorator.py' en un directorio de su PYTHONPATH. – unutbu

+0

Esta solución no se ajusta a mi problema porque 'decorator' supone que se realiza poco o ningún trabajo en la función del decorador principal, y la mayor parte del trabajo se realiza en la función interna devuelta. Ese no es mi caso: trabajo mucho antes de definir mi función devuelta. Además, asume que realmente llamaré a la función orinal desde el interior de la función devuelta, lo que no haré (es un sistema RPC), por lo que no tengo uso para la función recibida como el primer parámetro. – lvella

1

Esta funcionalidad es suministrada por la biblioteca estándar de Python inspect module, específicamente por inspect.getargspec.

>>> import inspect 
>>> def f(a, b, c=0, *args, **kwargs): return 
... 
>>> inspect.getargspec(f) 
ArgSpec(args=['a', 'b', 'c'], varargs='args', keywords='kwargs', defaults=(0,)) 
+2

Esto parece interesante, pero ¿existe entonces una manera de establecer realmente la firma de la llamada de la envoltura para que se vea lo mismo que la función original cuando se utiliza el comando de ayuda? – astrofrog