2010-11-08 50 views
4

给定一个装饰器方法列表,如何将这些应用于可调用方法?将一个装饰器列表应用于可调用?

例如,因为:

@foo 
@bar 
def baz(): 
    pass 

...是一样的:

def baz(): 
    pass 
baz = foo(bar(baz))) 

...一会认为与装饰的([foo, bar])的列表,他们可以应用动态地到baz

+0

“一将假设”?真?基于什么?是什么让你得出这个结论? – 2010-11-08 12:17:29

+2

@ S.Lott因为它是Python?我的一般假设是我可以做任何我想做的事情。 – aaronasterling 2010-11-08 12:31:39

+0

@aaronasterling,我想你会把Python和神秘的[DWIM](http://en.wikipedia.org/wiki/DWIM)计算机语言混淆起来。 – martineau 2010-11-08 20:00:26

回答

11

还有另一个装修工!

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。然后,如果您正在创建名单,则不必使用括号。如果列表是在其他地方创建的,我演示的方式会更好。

+3

如果你用这个定义yad:'def yad(* decorators):',那么你可以避免列表中的括号。 – recursive 2010-11-08 10:19:38

+0

@recursive这就是我原来的样子,但后来我看到OP使用了方括号,并且可能在其他地方构建了列表(因此强调不使用装饰器语法)。虽然好提。 – aaronasterling 2010-11-08 10:47:14

+0

谢谢,我用一个简单的循环去了:'换成d(装饰):baz = d(baz)' – 2010-11-17 15:52:46

2

随着alltime经典:

def compose(f, g): 
    def composed(*a, **k): 
     return g(f(*a, **k)) 
    return composed 

@compose(foo, compose(bar, baz)) 
def blam(): 
    pass 
相关问题