Python
Class decorator
Learn class-based decorators.
Class decorator
A class decorator makes a class callable through the __call__ method and uses that class as a decorator instead of a function. The instance behaves like a function.
The advantage: it can hold state while wrapping. For example, it can count how many times it was called in an instance attribute. The shape is:
class Counter:
def __init__(self, fn):
self.fn = fn
self.count = 0
def __call__(self, *args):
self.count += 1
return self.fn(*args)
A function decorated with @Counter is now a Counter instance; fn.count gives the call count.
Tracking state with a class decorator
The strength of class decorators is that they can hold state. You keep call counts, caches or timestamps in instance attributes.
Example: each call increments a counter and returns the result. If square(x) decorated with @Counter is called three times, square.count becomes 3.
Inside, self.fn(*args) runs the original function; self.count += 1 updates the counter. State stays on the instance; no global variable is needed.
Exercise Call counter with a class decorator
Write a class decorator named Counter. Its __init__(self, fn) stores the function on self.fn and sets self.count to 0. Its __call__(self, *args) increments self.count each call and returns self.fn(*args). Decorate square(x) with @Counter so it returns x * x. Call square(3), square(4) and square(5); end with print(square.count).
Show example solution
class Counter:
def __init__(self, fn):
self.fn = fn
self.count = 0
def __call__(self, *args):
self.count += 1
return self.fn(*args)
@Counter
def square(x):
return x * x
square(3)
square(4)
square(5)
print(square.count)
Test yourself
-
The call method in a class decorator
class Counter:
def __init__(self, fn):
self.fn = fn
self.count = 0
def ____(self, *args):
self.count += 1
return self.fn(*args)
Show answer
class Counter:
def __init__(self, fn):
self.fn = fn
self.count = 0
def __call__(self, *args):
self.count += 1
return self.fn(*args)
-
Where does a class decorator store call info?
- In a global variable
- In an instance attribute (like self.count)
- In a local variable
- In a module-level constant
Show answer
In an instance attribute (like self.count) — A class decorator stores state in self-prefixed instance attributes; each instance has its own counter.
-
Match the class decorator pieces
- __init__(self, fn)
- Holds the original function
- __call__(self, *args)
- Runs when called
- self.count
- State attribute
- self.fn(*args)
- Calls the original function
Next lesson: functools