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

Question:

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.

Asked By: Muhammad Yasirroni

||

Answers:

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']
Answered By: cards