3

I've attended a session about decorator pattern where most of the examples provided were in java.For instance in the example below the Pizza object is being decorated with Two toppings .

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

In python i've seen decorators being used in the scenarios like this

@applyTopping2
@applyTopping1
makePizza():
    pass

Though here I can see that the the makePizza function is being decorated with two functions , but it differs a lot from the class based approach of java. My question is do python decorators strictly implement the decorator pattern or do the implementation is a little different but the idea is same.

PS: I am not sure where to lookup the standard definition of the decorator pattern.though wikipedia gives an example in a dynamic language (JS) but my question still holds good :)

Bunny Rabbit
  • 8,213
  • 16
  • 66
  • 106
  • Nothing prevents Python decorators from being classes as well. – jsbueno Dec 14 '11 at 13:07
  • 1
    *Strictly implementing the decorator patter*? Is there a standard definition of how a decorator should look like? – Constantinius Dec 14 '11 at 13:08
  • 2
    I think the burden is upon you on getting a definition of what would be a "strict decorator pattern". (then, we Python fans can proceed on describe why the strictness is irrelevant and defend Python approach :-) ) – jsbueno Dec 14 '11 at 13:11
  • 1
    @jsbueno this is funny because it's really true. Anyway, check this: http://stackoverflow.com/questions/739654/understanding-python-decorators/1594484#1594484 . It's an example of how the decorators work in Python. You will see if it match your expectation of the design patter. – Bite code Dec 14 '11 at 13:18
  • I too was secretly hoping that somebody would come and defend the python approach but sadly the python wiki says they are diff ;(, any way i don't care , decorator pattern is good to know but i am gonna use python decorators only for now :) :) – Bunny Rabbit Dec 14 '11 at 13:25
  • According to the Wikipedia article on [Python decorators](http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators): "Despite the name, Python decorators are not an implementation of the decorator pattern". – martineau Jun 08 '13 at 13:09

3 Answers3

2

You should read this which explains what are python's decorators.

The "decorators" we talk about with concern to Python are not exactly the same thing as the DecoratorPattern [...]. A Python decorator is a specific change to the Python syntax that allows us to more conveniently alter functions and methods (and possibly classes in a future version). This supports more readable applications of the DecoratorPattern but also other uses as well.

So, you will be able to implement the "classical" decorator pattern with python's decorator, but you will be able to do much more (funny ;)) things with those decorators.

In your case, it could looks like :

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

And then you will get a Margherita :)

Cédric Julien
  • 78,516
  • 15
  • 127
  • 132
1

not a real answer, just a fun example on how one can do things in Python - compared to static languages:

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"

When pasting this code on the Python console:

>>> 
>>> print pizza()
Pizza, mozarella, anchove
jsbueno
  • 99,910
  • 10
  • 151
  • 209
1

The @decorator syntax in Python is nothing more than syntax sugar.

The code

@decorator
def foo():
    pass

is nothing more than

def foo():
    pass

foo = decorator(foo)

The final result just depends on what do you want for it to be.

You may use class as decorator and will get object instantiated from this class with foo as __init__ arg.

You may use object instantiated with some parameters as decorator like in code bellow

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

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

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

This is only you who decides what your code will look like and what it will do not any pattern or somebody from java world:)

lig
  • 3,567
  • 1
  • 24
  • 36
  • If one follows this logic, than the "class" keyword is just "syntax sugar" in Python, for `Decorator = type("Decorator", (object,), dict(__init__=lambda s, foo: setattr(s,"f", foo), __call__=lambda s: s.f()))` – jsbueno Dec 14 '11 at 13:38
  • but like with function we get an object of the called function here we don't – Bunny Rabbit Dec 15 '11 at 03:16