Применить список декораторов для вызова? - PullRequest
4 голосов
/ 08 ноября 2010

Учитывая список методов-декораторов, как применить их к вызываемому?

Например, с:

@foo
@bar
def baz():
    pass

... совпадает с:

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

... можно предположить, что со списком декораторов ([foo, bar]) они могут быть применены к baz динамически.

Ответы [ 2 ]

12 голосов
/ 08 ноября 2010

С еще одним декоратором!

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. Тогда вам не нужно использовать скобки, если вы создаете список in situ . Способ, который я продемонстрировал, лучше, если список создается в другом месте.

2 голосов
/ 08 ноября 2010

С классической историей:

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

@compose(foo, compose(bar, baz))
def blam():
    pass
...