Python 如何在decorator中混合使用*args、**kwargs和命名参数

Python 如何在decorator中混合使用*args、**kwargs和命名参数,python,arguments,decorator,Python,Arguments,Decorator,我想创建一个自定义装饰器,名为captain\u hook。它应该存储钩子-在修饰函数之前要调用的函数-并调用它们: def captain_hook(func): def closure(hooks=[], *args, **kwargs): for hook in hooks: hook(*args, **kwargs) return func(*args, **kwargs) return closure 现在我可

我想创建一个自定义装饰器,名为
captain\u hook
。它应该存储
钩子
-在修饰函数之前要调用的函数-并调用它们:

def captain_hook(func):
    def closure(hooks=[], *args, **kwargs):
        for hook in hooks: 
            hook(*args, **kwargs)
        return func(*args, **kwargs)
    return closure
现在我可以说:

@captain_hook
def sum(a, b):
    return a+b
sum.__defaults__[0].append(lambda arg: sys.stdout.write(str(arg))) #this lambda function prints argument
sum(1, 2) #should write (1, 2) and return 3

问题是我无法将参数传递给
closure
,导致
args
的第一个元素错误地解包到
hooks
参数:
sum(1,2)
设置
hook=1
a=2
b-未定义
。我该怎么做呢?

修改
\uuuuu默认值\uuuuu
是一种非常可疑的处理方法<代码>\uuuu默认值\uuuu用于参数默认值。如果钩子不会作为参数传递,则不应将其存储为参数默认值

如果您真的希望以后能够修改钩子,那么您应该使您的装饰器成为一个在自身上存储钩子的类。下面是一个例子:

class CaptainHook(object):
    def __init__(self, func):
        self.hooks = []
        self.func = func

    def __call__(self, *args, **kwargs):
        for hook in self.hooks:
            hook(*args, **kwargs)
        return self.func(*args, **kwargs)
然后:


你打算什么时候通过钩子?按照设置方式,使用
captain\u hook
时不指定任何钩子,调用
sum
时也不提供任何钩子,因此不涉及钩子。您想在定义函数还是调用函数时指定钩子?@BrenBarn我编辑了这个问题。我将在调用函数之前安装钩子。当我创建新对象时,它将受到函数调用的影响,并且应该适应变化,它的钩子将被调用。钩子是通过更改
sum.\uuuu默认值\uuuu
安装的。正如我所想,您已经编写了它。谢谢你的好例子,你的方法好多了,我的方法太粗糙了。
>>> @CaptainHook
... def sum(a, b):
...     return a+b
>>> sum(1, 2)
3
>>> def aHook(*args, **kwargs):
...     print "I am a hook!"
>>> sum.hooks.append(aHook)
>>> sum(1, 2)
I am a hook!
3