Строгие ли декораторы Python реализуют шаблон декоратора? - PullRequest
3 голосов
/ 14 декабря 2011

Я посетил сеанс о шаблоне декоратора, где большинство предоставленных примеров были на java. Например, в приведенном ниже примере объект Pizza украшен двумя начинками.

Pizza vegPizza = new ToppingsType1(new ToppingType2(new Pizza()))

В Python iВы видели, как в таких сценариях используются декораторы

@applyTopping2
@applyTopping1
makePizza():
    pass

Хотя здесь я вижу, что функция makePizza украшена двумя функциями, но она сильно отличается от подхода java, основанного на классах.Мой вопрос заключается в том, строго ли Python-декораторы реализуют шаблон декоратора или реализация немного отличается, но идея та же.

PS: Я не уверен, где искать стандартное определение шаблона декоратора. Хотя википедияприводит пример на динамическом языке (JS), но мой вопрос все еще остается в силе :)

Ответы [ 3 ]

2 голосов
/ 14 декабря 2011

Вы должны прочитать это , которое объясняет, что такое декораторы Python.

«Декораторы», о которых мы говорим с беспокойством о Python, - это не то же самое, что DecoratorPattern [...].Декоратор Python - это конкретное изменение синтаксиса Python, которое позволяет нам более удобно изменять функции и методы (и, возможно, классы в будущей версии).Это поддерживает более удобочитаемые приложения DecoratorPattern , но также и другие применения.

Таким образом, вы сможете реализовать «классический» шаблон декоратора с помощью декоратора python, но выс этими декораторами можно будет делать гораздо больше (смешно;) вещей.

В вашем случае это может выглядеть так:

def applyTopping1(functor):
    def wrapped():
        base_pizza = functor()
        base_pizza.add("mozzarella")
        return base_pizza
    return wrapped

def applyTopping2(functor):
    def wrapped():
        base_pizza = functor()
        base_pizza.add("ham")
        return base_pizza
    return wrapped

И тогда вы получите Маргариту :)

1 голос
/ 14 декабря 2011

Синтаксис @decorator в Python - это не что иное, как синтаксический сахар.

код

@decorator
def foo():
    pass

не более чем

def foo():
    pass

foo = decorator(foo)

Окончательный результат зависит только от того, что вы хотите, чтобы он был.

Вы можете использовать класс как decorator и получите экземпляр объекта из этого класса с foo как __init__ arg.

Вы можете использовать объект, созданный с некоторыми параметрами, как декоратор, как в коде ниже

class Decorator(object):
    def __init__(self, arg1, arg2):
        pass

    def __call__(self, foo):
        return foo()

@Decorator(arg1_value, arg2_value)
def foo():
    pass

Это только вы, кто решает, как будет выглядеть ваш код и что он не будет делать ни с каким шаблоном, ни с кем-либо из мира Java:)

1 голос
/ 14 декабря 2011

не настоящий ответ, просто забавный пример того, как можно что-то делать в Python - по сравнению со статическими языками:

def pizza_topping_decorator_factory(topping):
    def fresh_topping_decorator(pizza_function):
        def pizza_with_extra_topping(*args, **kw):
            return pizza_function(*args, **kw) + ", " + topping
        return pizza_with_extra_topping
    return fresh_topping_decorator


mozzarela = pizza_topping_decorator_factory("mozarella")
anchove = pizza_topping_decorator_factory("anchove")

@anchove
@mozzarela
def pizza():
    return "Pizza"

При вставке этого кода в консоль Python:

>>> 
>>> print pizza()
Pizza, mozarella, anchove
...