Search code examples
pythondecoratorpython-decorators

Class method as a decorator


I have a class where I have multiple methods. I want to use one of the methods as a decorator for other methods. For this I am using following syntax:

@self.action
def execute(self,req):    

where action is other method in my class. But it doesn't work and throws exception as

name 'self' is not defined

Solution

  • You cannot use a method of the class while defining it; there is no self within the class nor is the class 'baked' yet to even access any class.

    You can treat methods as functions to use as a decorator:

    class SomeClass():
        def action(func):
            # decorate
            return wrapper
    
        @action
        def execute(self, req):
            # something
    

    If action is defined on a base class, then you'd have to refer to the name via the base class:

    class Base():
        @staticmethod
        def action(func):
            # decorate
            return wrapper
    
    class Derived(Base):
        @Base.action
        def execute(self, req):
            # something
    

    For Python 2, you'd have to make action a static method here, as otherwise you get an unbound method that'll complain you cannot call it without an instance as the first argument. In Python 3, you can leave off the @staticmethod decorator there, at least for the purposes of the decorator.

    But note that action cannot then be used as a method directly; perhaps it should not be part of the class at all at that point. It is not part of the end-user API here, presumably the decorator is not used by consumers of the instances of these classes.