如何对一个可调用对象应用多个装饰器?
假设你有一堆装饰器方法,你想把它们应用到一个可以调用的东西上,比如一个函数。
举个例子,因为:
@foo
@bar
def baz():
pass
...和下面这个是一样的:
def baz():
pass
baz = foo(bar(baz)))
...所以人们会想,如果有一个装饰器的列表(比如[foo, bar]
),那么就可以动态地把它们应用到baz
这个函数上。
2 个回答
2
这是一个经典的例子:
def compose(f, g):
def composed(*a, **k):
return g(f(*a, **k))
return composed
@compose(foo, compose(bar, baz))
def blam():
pass
14
又来了一个装饰器!
def yad(decorators):
def decorator(f):
for d in reversed(decorators):
f = d(f)
return f
return decorator
示例用法
list_of_decorators = [foo, bar]
@yad(list_of_decorators)
def foo():
print 'foo'
如果没有装饰器的语法,它看起来会是这样的
func = yad(list_of_decorators)(func)
如果你想把同一个列表应用到多个函数上,可以这样做:
dec = yad(list_of_decorators)
func1 = dec(func1)
@dec
def func2():
pass
正如递归在评论中提到的,你可以定义一个叫 yad
(我相信还有更好的名字)来接受 *decorators
,而不是 decorators
。这样的话,如果你在创建列表的时候不需要用括号就可以了。我的示范方式更适合在其他地方创建列表的情况。