[英]How to mix *args, **kwargs and named arguments in decorator
I want to create a custom decorator, called captain_hook
. 我想创建一个自定义的装饰器,称为
captain_hook
。 It should store hooks
- functions to be called before the decorated function - and call them: 它应该存储
hooks
(要在修饰的函数之前调用的函数)并调用它们:
def captain_hook(func):
def closure(hooks=[], *args, **kwargs):
for hook in hooks:
hook(*args, **kwargs)
return func(*args, **kwargs)
return closure
Now I could say: 现在我可以说:
@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
The problem is that I can't pass the arguments to closure
, cause first element of args
mistakingly unpacks to hooks
argument: sum(1, 2)
sets hook=1
, a=2
, b - undefined
. 问题是我无法将参数传递给
closure
,导致args
第一个元素错误地解压缩到hooks
参数: sum(1, 2)
设置hook=1
, a=2
, b - undefined
。 How do I do that? 我怎么做?
Modifying __defaults__
is a very dubious way to handle this. 修改
__defaults__
是一种处理此问题的非常可疑的方法。 __defaults__
is for argument default values. __defaults__
用于参数默认值。 If your hooks aren't going to be passed as arguments, you shouldn't store them as an argument default value. 如果您的钩子不作为参数传递,则不应将其存储为参数默认值。
If you really want to be able to modify the hooks later on, you should make your decorator a class that stores the hooks on itself. 如果您确实希望以后能够修改钩子,则应使装饰器成为一个将钩子自身存储的类。 Here's an example:
这是一个例子:
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)
Then: 然后:
>>> @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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.