Python Instance Method vs Classmethod: What Gets Passed
python instance method vs classmethod: Understand the difference between Python instance methods and classmethods: what gets passed, how inheritance behaves, and when...
The difference between a Python instance method vs classmethod comes down to what Python passes as the first argument when the method is called. An instance method receives the instance (self), while a classmethod receives the class itself (cls). That single difference drives when each is useful, how they behave under inheritance, and how they should be designed.
The Core Difference: What Gets Passed as the First Argument
When you define a method inside a class, Python binds the first parameter according to how the method is declared. A normal instance method takes self as its first parameter, and Python fills that parameter with the instance on which the method was called. A classmethod, declared with @classmethod, takes cls as its first parameter, and Python fills it with the class, not an instance.
class Order: def instance_method(self): return f"instance: {self}" @classmethod def class_method(cls): return f"class: {cls}"
Calling Order().instance_method() passes the Order instance as self. Calling Order.class_method() passes the Order class itself as cls. The classmethod does not need an instance to exist; the class is always available.
Instance Methods: Binding to self
An instance method is the default method type in Python. When you define a method without a decorator, it is an instance method, and its first parameter conventionally receives the instance.
class ShoppingCart: def __init__(self): self.items = [] def add_item(self, name, price): self.items.append({"name": name, "price": price}) return self.total() def total(self): return sum(item["price"] for item in self.items)
Here add_item and total both depend on self.items, which exists only on a specific ShoppingCart instance. The instance method can read and mutate instance state, which is its defining characteristic. If you tried to call ShoppingCart.add_item("book", 10) without an instance, Python would raise a TypeError because self would be missing.
Instance methods are the right choice whenever the behavior depends on the state of a particular object. They are the default for a reason: most methods in a class operate on instance data.
Class Methods: Binding to cls
A classmethod receives the class rather than an instance. The @classmethod decorator changes how Python binds the first argument.
class Currency: conversion_rates = {"USD": 1.0, "EUR": 0.92, "JPY": 149.5} def __init__(self, amount, code): self.amount = amount self.code = code @classmethod def from_code(cls, code): return cls(0, code) @classmethod def available_codes(cls): return list(cls.conversion_rates.keys())
from_code and available_codes do not need any instance state. They operate on class-level data (conversion_rates) and can be called directly on the class:
codes = Currency.available_codes() usd = Currency.from_code("USD")
Because cls is passed, the classmethod can access class attributes and can also create new instances of the class. The key point is that no instance needs to exist for the call to succeed.
Alternative Constructors with @classmethod
The most common practical use of a classmethod is an alternative constructor. A class may have one __init__ that takes a particular set of parameters, but callers may have data in a different format. A classmethod can parse that data and construct an instance through the normal __init__.
from datetime import datetime class Event: def __init__(self, name, start_time): self.name = name self.start_time = start_time @classmethod def from_iso_string(cls, name, iso_string): start_time = datetime.fromisoformat(iso_string) return cls(name, start_time)
Event.from_iso_string("deploy", "2025-06-01T14:00:00") parses the ISO string and delegates to the regular constructor. The classmethod keeps parsing logic out of __init__, leaving __init__ focused on storing validated data.
This pattern matters because cls is the actual class on which the method was called. If a subclass inherits from_iso_string, calling it on the subclass returns an instance of the subclass, not the parent class. That is the behavior you want from an alternative constructor.
How Inheritance Changes Class Method Behavior
The cls argument is resolved at call time based on the class through which the method is invoked. This is a subtle but important difference from a function that hardcodes a class name.
class Animal: def __init__(self, name): self.name = name @classmethod def create(cls, name): return cls(name) class Dog(Animal): pass dog = Dog.create("Rex") print(type(dog)) # <class '__main__.Dog'>
Because Dog.create passes Dog as cls, the returned object is a Dog, not an Animal. If create had instead hardcoded Animal(name), subclasses would silently get parent instances, breaking polymorphic behavior.
This is the reason classmethods are preferred over hardcoding the class name inside a method. When you write cls(...), you preserve the actual class in inheritance chains. The same rule applies to accessing class attributes: inside a classmethod, cls.conversion_rates resolves against the subclass if the subclass overrides that attribute.
When a Class Method Is the Wrong Choice
A classmethod cannot access instance state because it never receives an instance. If the behavior needs self.some_attribute, a classmethod is the wrong tool. That is the most common mistake developers make when refactoring: moving a method that reads instance attributes into a classmethod, only to find the attribute is unavailable.
class Report: def __init__(self, rows): self.rows = rows @classmethod def row_count(cls): # This will fail: cls has no 'rows' attribute. return len(cls.rows)
Report.row_count() would raise an AttributeError because cls is the class, not an instance. The method needs instance state, so it must be an instance method:
class Report: def __init__(self, rows): self.rows = rows def row_count(self): return len(self.rows)
The rule is straightforward: if the method reads or mutates instance attributes, make it an instance method. If the method only needs class-level data or needs to construct an instance, a classmethod is appropriate.
Choosing Between Instance and Class Methods
The decision reduces to what the method needs access to. An instance method gets the instance and can read both instance and class attributes. A classmethod gets only the class and can read class attributes but not instance attributes.
| Need | Method type |
|---|---|
| Read or mutate instance state | instance method |
| Access class-level configuration | classmethod |
| Build an instance from alternative input | classmethod |
| Called without creating an instance | classmethod |
| Polymorphic factory for subclasses | classmethod |
| Operate on a specific object's data | instance method |
A classmethod is appropriate when the operation is conceptually tied to the class itself: parsing input into an instance, exposing class-level configuration, or providing a factory that respects subclassing. An instance method is appropriate when the operation depends on the state of a particular object, which is the majority of methods in a typical class.
There is also a third option worth knowing: a @staticmethod receives neither self nor cls. It is a plain function namespaced inside the class. Use it only when the method needs no access to the class or instance at all. Most code that reaches for @staticmethod can often be a module-level function, but keeping it inside the class can improve discoverability when it is conceptually tied to the class.
The choice between instance method and classmethod is not about style. It is about what data the method must access and how the method should behave when subclasses are involved. When you need instance state, use an instance method. When you need class-level behavior that must respect inheritance, use a classmethod.