Class method decorator with self arguments?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python decorators often confuse people when methods are involved because self is not passed to the decorator at definition time. The decorator receives the function object, and only later, when the method is called on an instance, does the wrapper receive self. Once you separate those two moments, method decorators become much easier to reason about.
Decorators Wrap Functions First
A decorator is applied when the class body is executed, before any instance exists. That means this function:
receives the undecorated function object, not an instance and not self.
When you use it on an instance method:
the wrapper gets called later with self as the first positional argument because that is how instance methods work in Python.
Accessing self in the Wrapper
If you need the instance, read it from the wrapper arguments.
Here self is not a special decorator feature. It is just the first argument passed when the bound method is invoked.
Decorator Factories When You Need Parameters
If the decorator itself needs configuration, use a decorator factory.
The outer function receives the decorator configuration. The inner wrapper receives self when the method is called.
@classmethod Changes the First Argument
A class method does not receive self. It receives cls, the class object.
The order matters. The decorator wrapping the plain function and @classmethod converting it into a class method are distinct steps.
If you reverse the order, you are decorating a classmethod descriptor object instead of the underlying function, which usually is not what you want.
Instance Methods, Class Methods, and Static Methods
Keep the first argument model straight:
- instance method: first argument is
self - class method: first argument is
cls - static method: no automatic first argument
That is why a decorator written for instance methods does not automatically fit a static method or class method. The wrapper signature must match how the decorated callable will be invoked.
Preserve Metadata with wraps
Always use functools.wraps unless you have a strong reason not to.
Without it, the wrapped method loses metadata such as:
- '
__name__' - '
__doc__' - inspection friendliness
This becomes painful in debugging, testing, and frameworks that inspect callables.
Common Pitfalls
- Expecting
selfto be available when the decorator itself is created. - Forgetting that the wrapper, not the decorator factory, receives
self. - Writing one wrapper signature and assuming it works for instance, class, and static methods.
- Applying
@classmethodand a custom decorator in the wrong order. - Omitting
@wrapsand losing method metadata.
Summary
- Decorators receive the function object at definition time, not
self. - For instance methods,
selfappears later as the first wrapper argument. - For class methods, the first wrapper argument is
cls. - Use a decorator factory when the decorator needs configuration.
- Keep method type and decorator order straight, especially around
@classmethod.

