保留签名的Python装饰器(关闭版本)

时间:2018-10-05 18:06:01

标签: python python-2.7 decorator

我的装饰器是“封闭式”的;在返回修饰后的功能之前,它会做一些工作。

借用这个著名的问题:Preserving signatures of decorated functions

def args_as_ints(f):

    time.sleep(1) # hard at work

    def g(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return f(*args, **kwargs)
    return g

functools.wraps未在Python 2中保留签名。

from functools import wraps

def args_as_ints(f):

    time.sleep(1) # hard at work

    @wraps(f) 
    def g(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return f(*args, **kwargs)
    return g


@args_as_ints
def funny_function(x, y, z=3):
    """Computes x*y + 2*z"""
    return x*y + 2*z

help(funny_function)

显示

Help on function funny_function in module __main__:

funny_function(*args, **kwargs)
    Computes x*y + 2*z

decorator模块似乎不支持这种样式的装饰器。

也相关:Preserve Signature in Decorator python 2

2 个答案:

答案 0 :(得分:0)

您可以使用wrapt模块。

请记住,wrapt装饰器的界面与标准python装饰器的界面不同。我强烈建议您阅读wrapt documentation。无论如何,这是wrapt.decorator修饰器的基本实现:

import wrapt

def args_as_ints(f):
    time.sleep(1) # hard at work

    @wrapt.decorator
    def g(f, instance, *args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return f(*args, **kwargs)

    return g(f)  # apply the decorator to the function

请注意,我的实现完全忽略了instance参数,因此它对于实例方法将无法正常工作。

但是,它确实保留了修饰函数的签名:

Help on function funny_function in module __main__:

funny_function(x, y, z=3)
    Computes x*y + 2*z

答案 1 :(得分:0)

设法在这里找到答案:https://decorator.readthedocs.io/en/latest/tests.documentation.html#dealing-with-third-party-decorators

def args_as_ints(f):

    time.sleep(1)

    def g(*args, **kwargs):
        args = [int(x) for x in args]
        kwargs = dict((k, int(v)) for k, v in kwargs.items())
        return f(*args, **kwargs)

    return decorator.FunctionMaker.create(
        f, 'return decfunc(%(signature)s)',
        dict(decfunc=g, __wrapped__=f))