在python中对参数进行操作的嵌套函数修饰符

2024-10-01 17:24:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个函数修饰符,它将对函数的第一个参数应用转换。如果我只修饰一次函数就可以了,但是如果我修饰了两次,就会出错。下面是一些代码来演示这个问题,它是我正在处理的代码的简化版本。我已经排除了进行转换的代码,以免分散问题的注意力

from inspect import getargspec
from functools import wraps

def dec(id):
    def _dec(fn):
        @wraps(fn)
        def __dec(*args, **kwargs):
            if len(args):
                return fn(args[0], *args[1:], **kwargs)
            else:
                first_arg = getargspec(fn).args[0]
                new_kwargs = kwargs.copy()
                del new_kwargs[first_arg]
                return fn(kwargs[first_arg], **new_kwargs)
        return __dec
    return _dec

@dec(1)
def functionWithOneDecorator(a, b, c):
    print "functionWithOneDecorator(a = %s, b = %s, c = %s)" % (a, b, c)

@dec(1)
@dec(2)
def functionWithTwoDecorators(a, b, c):
    print "functionWithTwoDecorators(a = %s, b = %s, c = %s)" % (a, b, c)

functionWithOneDecorator(1, 2, 3)
functionWithOneDecorator(1, b=2, c=3)
functionWithOneDecorator(a=1, b=2, c=3)
functionWithOneDecorator(c=3, b=2, a=1)

functionWithTwoDecorators(1, 2, 3)
functionWithTwoDecorators(1, b=2, c=3)
functionWithTwoDecorators(a=1, b=2, c=3)
functionWithTwoDecorators(c=3, b=2, a=1)

当我运行上述代码时,我得到以下输出:

^{pr2}$

这是因为当第二个decorator检查它所装饰的函数以找到参数名时,它失败了,因为它正在装饰一个decorator,并且只需要*args和**kwargs。在

我可以想出解决这个问题的方法,这些方法在上面的代码中可以工作,但是如果一个函数用我的装饰器和另一个来自第三方的函数来修饰,它仍然会崩溃。有没有解决这个问题的通用方法?还是有更好的方法来达到同样的效果?在

更新:感谢@Hernan指出了decorator module。它正好解决了这个问题。现在我的代码如下:

from decorator import decorator

def dec(id):
    @decorator
    def _dec(fn, *args, **kwargs):
        return fn(args[0], *args[1:], **kwargs)
    return _dec

@dec(1)
def functionWithOneDecorator(a, b, c):
    print "functionWithOneDecorator(a = %s, b = %s, c = %s)" % (a, b, c)

@dec(1)
@dec(2)
def functionWithTwoDecorators(a, b, c):
    print "functionWithTwoDecorators(a = %s, b = %s, c = %s)" % (a, b, c)

functionWithOneDecorator(1, 2, 3)
functionWithOneDecorator(1, b=2, c=3)
functionWithOneDecorator(a=1, b=2, c=3)
functionWithOneDecorator(c=3, b=2, a=1)

functionWithTwoDecorators(1, 2, 3)
functionWithTwoDecorators(1, b=2, c=3)
functionWithTwoDecorators(a=1, b=2, c=3)
functionWithTwoDecorators(c=3, b=2, a=1)    

干净多了,而且它起作用了!


Tags: 方法函数代码fromimportreturndefargs
1条回答
网友
1楼 · 发布于 2024-10-01 17:24:49

问题是修饰函数的签名不是原始函数的签名(getargspec)。它在decorator module的帮助下得到了很好的解释,你可以用它来解决你的问题。基本上,您应该使用一个保持签名的装饰器,以便第二个装饰器看到与第一个相同的签名。在

相关问题 更多 >

    热门问题