Search code examples
pythonoopdesign-patternsdecoratorwrapper

python decorating an object with @


I want to achieve the decorator design pattern in python using the @ syntax, my code:

class Sandwich():
    height = 5
    width = 8

    def ingredients(self):
        print("I have bread")
    
class Cheese_decorator():
    def __init__(self,obj):
        self.obj = obj
        #something else here so the object becomes the same as the passed one except for the methods to decorate below

    #decorated method
    def ingredients(self):
        self.obj.ingredients()
        print("I also have cheese")
     
    #any other method to decorate here

sandwich = Sandwich() # this sandwich wont be decorated
cheese_sandwich = Cheese_decorator(Sandwich()) # this sandwich is decorated

sandwich.ingredients() # prints I have bread
cheese_sandwich.ingredients() # prints I have bread I also have cheese

is there anything I can do like:

sandwich = Sandwich()
cheese_sandwich = @Cheese_decorator
                  sandwich

? I want to have the decorated object as a var


Solution

  • Regardless of whatever theoretical text you got to read "decorator pattern" - that is not what decorators are in Python.

    The @ syntax is meant to transform either a function or a class - and usually, the result is callable itself. If a class is decorated, the result is the class modified (or a new class), that will create instances, not instances themselves, like in your example.

    Moreover, as it is applicable either on a def or on a class block, the resulting name for the decorated object is the name given in the statement. (Either the name after def or after the class keyword). It also implies the @ syntax composes with one statement, and therefore is not an "expression" - and therefore invalid on the right side of an assignment, or other arbitrary places: the @decorator syntax requires it to be in a line by itself.

    That said, your code example, using the the cheese_sandwich = Cheese_decorator(Sandwich()) as it is, conforms with the "decorator pattern" from text books, and you may call it so. It just won't work with the "decorator syntax" from Python.