问题 将呼叫签名复制到装饰者


如果我做以下事情

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

然后输入 help myfunction,我得到:

Help on function myfunction in module __main__:

myfunction(*args, **kwargs)
    My docstring

因此,名称和文档字符串被正确复制。在这种情况下,是否还有一种方法可以复制实际的呼叫签名 (a, b, c)


1689
2018-06-06 03:10


起源



答案:


这是一个使用Michele Simionato的例子 装饰模块 修复签名:

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

9
2018-06-08 12:57



这是一个很好的答案,但却依赖于另一个非官方的第三方。有没有使用装饰模块的简单方法? - Jason Morgan
该 decorator module是一个由<250行组成的单个文件。我不认为删除相关部分会为您节省大量代码。最简单的方法是安装装饰模块。请注意,如果您无法在系统范围内安装它,则可以始终保存本地副本 decorator.py 到PYTHONPATH中的目录。 - unutbu
这个解决方案不适合我的问题,因为 decorator 假设在父装饰器函数上完成很少或没有工作,并且大部分工作在内部返回函数中完成。这不是我的情况:在定义返回的函数之前,我做了很多工作。此外,它假设我实际上将从返回的函数内部调用orinal函数,我不会做什么(它是一个RPC系统)所以我没有使用作为第一个参数接收的函数。 - lvella


答案:


这是一个使用Michele Simionato的例子 装饰模块 修复签名:

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

9
2018-06-08 12:57



这是一个很好的答案,但却依赖于另一个非官方的第三方。有没有使用装饰模块的简单方法? - Jason Morgan
该 decorator module是一个由<250行组成的单个文件。我不认为删除相关部分会为您节省大量代码。最简单的方法是安装装饰模块。请注意,如果您无法在系统范围内安装它,则可以始终保存本地副本 decorator.py 到PYTHONPATH中的目录。 - unutbu
这个解决方案不适合我的问题,因为 decorator 假设在父装饰器函数上完成很少或没有工作,并且大部分工作在内部返回函数中完成。这不是我的情况:在定义返回的函数之前,我做了很多工作。此外,它假设我实际上将从返回的函数内部调用orinal函数,我不会做什么(它是一个RPC系统)所以我没有使用作为第一个参数接收的函数。 - lvella


试试吧 decorator 模块,可在此处获得: http://pypi.python.org/pypi/decorator/3.2.0

相关部分的文档: http://micheles.googlecode.com/hg/decorator/documentation.html#statement-of-the-problem


3
2018-06-06 03:49





此功能由Python标准库提供 检查模块,特别是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,))

1
2018-06-06 03:47



这看起来很有趣,但有没有办法实际设置包装器的调用签名,以便在使用help命令时看起来与原始函数的调用签名相同? - astrofrog