Class method differences in Python bound, unbound and static
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Python method binding can look confusing because instance methods, class methods, and static methods all live inside classes but behave differently when accessed. The most important clarification is that “unbound method” is mostly a Python 2 term; in modern Python 3, a function accessed through the class is usually just a plain function descriptor until it is bound.
Instance Methods Become Bound to an Object
A normal method defined in a class becomes a bound method when you access it through an instance. Python automatically supplies the instance as the first argument.
Under the hood, u.greet is a bound method object that remembers u as self. That is why the caller supplies only the remaining argument.
You can see the difference explicitly:
This binding behavior is what makes instance methods feel natural in Python object-oriented code.
Accessing Through the Class Is Different
If you access the same function through the class, Python 3 does not create the old Python 2 style “unbound method” object. You simply get the underlying function-like descriptor, and you must pass the instance yourself.
This is why the term “unbound method” is historical in modern Python discussions. In Python 3, it is clearer to say:
- '
u.greetis bound tou' - '
User.greetis a function retrieved from the class'
The practical rule is simple: instance access binds, class access does not.
@classmethod Binds to the Class
A class method receives the class itself as the first argument, traditionally named cls.
This is useful for:
- alternate constructors
- logic that depends on the actual subclass
- behavior that belongs to the class, not an instance
Because cls is passed automatically, subclasses inherit class methods naturally.
Here cls becomes Admin, not User, which is why class methods are often the right tool for factory-style APIs.
@staticmethod Does Not Bind Anything
A static method is just a function stored in the class namespace. It does not receive self or cls automatically.
The behavior is the same whether you call it from the class or an instance, because nothing is being bound.
Static methods are best for helper logic that is conceptually related to the class but does not need instance or class state.
Choose the Right Method Type
A good rule of thumb:
- instance method when you need object state
- class method when you need class-level construction or polymorphic type behavior
- static method when you need a namespaced helper
If a method needs self, make it an instance method. If it does not need either self or cls, question whether it belongs inside the class at all.
Common Pitfalls
- Referring to “unbound methods” in Python 3 without clarifying the Python 2 historical context causes confusion.
- Using
@staticmethodwhen the logic really needs subclass-aware construction usually blocks extensibility. - Using
@classmethodfor code that only belongs to one instance makes the API less clear. - Forgetting that
User.greetrequires an explicit instance argument leads to argument-count errors. - Treating static methods as a default choice instead of as a deliberate design tool often produces awkward class APIs.
Summary
- Instance methods bind
selfautomatically when accessed through an object. - In Python 3, class access usually returns the underlying function rather than a special unbound-method object.
- '
@classmethodbinds the class asclsand is ideal for alternate constructors.' - '
@staticmethodbinds nothing and works like a namespaced helper function.' - Choose the method type based on what state or type information the logic actually needs.

