Python
Class Methods
Bound Methods
Unbound Methods
Static Methods

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.

python
1class User:
2    def greet(self, prefix):
3        return f"{prefix} {self.__class__.__name__}"
4
5
6u = User()
7print(u.greet("hello"))

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:

python
print(type(u.greet))
print(u.greet.__self__)

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.

python
1class User:
2    def greet(self, prefix):
3        return f"{prefix} {self.__class__.__name__}"
4
5
6u = User()
7print(User.greet(u, "hello"))

This is why the term “unbound method” is historical in modern Python discussions. In Python 3, it is clearer to say:

  • 'u.greet is bound to u'
  • 'User.greet is 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.

python
1class User:
2    def __init__(self, name):
3        self.name = name
4
5    @classmethod
6    def from_upper(cls, raw_name):
7        return cls(raw_name.lower())
8
9
10u = User.from_upper("ADA")
11print(u.name)

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.

python
1class Admin(User):
2    pass
3
4
5admin = Admin.from_upper("ROOT")
6print(type(admin).__name__)

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.

python
1class MathTools:
2    @staticmethod
3    def add(a, b):
4        return a + b
5
6
7print(MathTools.add(2, 3))
8print(MathTools().add(2, 3))

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 @staticmethod when the logic really needs subclass-aware construction usually blocks extensibility.
  • Using @classmethod for code that only belongs to one instance makes the API less clear.
  • Forgetting that User.greet requires 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 self automatically when accessed through an object.
  • In Python 3, class access usually returns the underlying function rather than a special unbound-method object.
  • '@classmethod binds the class as cls and is ideal for alternate constructors.'
  • '@staticmethod binds nothing and works like a namespaced helper function.'
  • Choose the method type based on what state or type information the logic actually needs.

Course illustration
Course illustration

All Rights Reserved.