我想创建一个名为captain_hook
的自定义装饰器。它应该存储hooks
- 在装饰函数之前调用的函数 - 并调用它们:
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)
设置{{ 1}},hook=1
,a=2
。我该怎么做?
答案 0 :(得分:1)
修改__defaults__
是处理此问题的一种非常可疑的方法。 __defaults__
用于参数默认值。如果您的钩子不会作为参数传递,则不应将它们存储为参数默认值。
如果你真的希望以后能够修改钩子,你应该让你的装饰器成为一个存储钩子的类。这是一个例子:
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)
然后:
>>> @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