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