Search code examples
pythonpython-3.xpython-decoratorspython-class

Python decorate `class.method` that modify on `class.self`


How to access self of the decorated method?

Based on this answer, the self refer to the decorator:

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print(self.func.__name__)
        self.counter += 1
        return self.func(*args, **kwargs)


class A:
    def __init__(self):
        self.counter = 0
    @Decorator
    def method1(self):
        pass

Above example will cause:

      5 def __call__(self, *args, **kwargs):
----> 6     self.counter += 1
      7     return self.func(*args, **kwargs)

AttributeError: 'Decorator' object has no attribute 'counter'

NOTE:

The return self.func(*args, **kwargs) is also causing error. I don't yet fully understand how to pass that to A.method1. The point is just that I want to update counter and printing self.func.__name__, that is all.


Solution

  • Here an example with a function-like decorator, it can be generalized with no afford to other cases.

    Hint: when using class decorators use another identifier for the self of the other class, otherself, ...

    def dec(f):
        def __wrapper(self, *args, **kwargs):
            self.counter += 1
            self.c.append(f.__name__)
            return f(self, *args, **kwargs)
        return __wrapper
    
    
    class A:
        def __init__(self):
            self.counter = 0
            self.c = []
    
        @dec
        def method1(self):
            pass
    
    a = A()
    a.method1()
    a.method1()
    print(a.counter, a.c)
    2 ['method1', 'method1']