Q1Which decorator do you use to define a static method?
Instance, Class, and Static Methods — The Three Method Types
Learn Python's three method types — instance, class, and static — with diagrams. Walk through using self / cls / no first argument and when to choose each.
Last time we covered the difference between class and instance variables. Every method we've written so far in def method(self, ...) form is an instance method, but Python classes have two more kinds — class methods and static methods. This time we'll sort out the three types and how to choose between them.
There Are Three Kinds of Methods
Methods in a Python class fall into three kinds, distinguished by what they take as their first argument:
- Instance method — first parameter self. Receives the instance itself.
- Class method — first parameter cls. Receives the class itself. Decorated with @classmethod.
- Static method — no first parameter. Takes neither self nor cls. Decorated with @staticmethod.
The kind determines what each method can reach. Only instance methods can touch instance variables self.x. Class methods are how you work with class variables from the class side, and static methods are for pure logic that touches neither.
Instance Methods — Taking self
The def method(self, ...) form you've been writing all along is an instance method. The first parameter self is filled in automatically with the instance the method was called on, so you can reach instance variables as self.name.
When you write apple.show(), Python internally translates it to Product.show(apple). You can think of methods as "functions that take an instance as their first argument."
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def total_with_tax(self, tax_rate): # instance method
return int(self.price * (1 + tax_rate))
apple = Product("apple", 150)
print(apple.total_with_tax(0.1)) # 165
# Internally the same as this
print(Product.total_with_tax(apple, 0.1)) # 165
__init__ sets apple.price = 150 → ② calling apple.method(0.1) puts apple into self → ③ self.price reads the value set on the instance.Class Methods — @classmethod and cls
A class method is defined with the @classmethod decorator, with cls as the first parameter (a conventional name). cls automatically holds the class itself — in this case the Product blueprint.
Use class methods when you want to read or write a class variable or build and return a single instance (a factory). You can also call them through an instance (apple.method()), but calling them on the class as Product.method() is the standard.
class Product:
total_count = 0 # class variable
def __init__(self, name, price):
self.name = name
self.price = price
Product.total_count += 1
@classmethod # ① returns a class variable
def get_total(cls):
return f"{cls.total_count} products registered"
@classmethod # ② builds and returns an instance (factory)
def from_csv_row(cls, row):
name, price = row.split(",")
return cls(name, int(price))
Product("apple", 150)
Product("banana", 80)
print(Product.get_total()) # 2 products registered
orange = Product.from_csv_row("orange,120")
print(orange.name, orange.price) # orange 120
get_total(cls) (decorated with @classmethod) as Product.get_total() automatically puts the Product class itself into cls. From there you can reach class variables as cls.total_count.def total_with_tax(self, tax_rate):- Call:
apple.total_with_tax(0.1) - →
selfbecomesapple - Reaches the instance variable self.price
- Decorated with
@classmethod def get_total(cls):- Call:
Product.get_total()(from the class) - →
clsbecomesProduct - Reaches the class variable cls.total_count
Static Methods — @staticmethod
A static method is defined with @staticmethod and takes neither self nor cls. It's "a plain function that lives in the class" — completes its work using only its arguments, with no access to instance or class variables.
It fits cases where the work is related to the class but doesn't depend on a particular instance or class state — input validation, formatting, pure computations using constants. Use it to keep utility functions next to the related class instead of writing them as standalone functions.
class Product:
def __init__(self, name, price):
if not Product.is_valid_price(price):
raise ValueError(f"invalid price: {price}")
self.name = name
self.price = price
@staticmethod
def is_valid_price(price): # no self, no cls
return 0 <= price <= 1_000_000
print(Product.is_valid_price(150)) # True
print(Product.is_valid_price(-1)) # False
# Product("apple", -1) # ValueError: invalid price: -1
Static Methods Work from the Class or the Instance
Both Product.is_valid_price(150) and apple.is_valid_price(150) work the same. But since the method doesn't actually use the instance, calling it on the class makes the intent clearer. Writing apple.is_valid_price(...) makes a reader pause and wonder "is this depending on apple's state?" — best avoided.
Choosing Between the Three
Which one to use can be decided mechanically based on "what the method needs to touch."
- Touches instance variables (self.x) → instance method
- Only touches class variables (cls.x) → class method
- Touches neither (just argument-driven) → static method
When in doubt: first check whether you touch instance variables. If not, check class variables. If neither, static. That order won't steer you wrong.
self.x? Next: do you handle class variables? If neither, static is the right pick.| Type | Decorator | 1st parameter | Typical use |
|---|---|---|---|
| Instance method | none | self | Regular methods that read/write self.x |
| Class method | @classmethod | cls | Read/write class variables, factories |
| Static method | @staticmethod | none | Validation, formatting, pure logic |
With this article you've covered the three method types — instance / class / static — and how to choose between them. That rounds out the core toolkit of classes, instances, attributes, and methods in Python. From here, you can move into the three pillars of object-oriented programming: encapsulation (controlling attribute visibility), inheritance (carrying over capabilities from another class), and polymorphism (the same method name behaving differently per type).
Knowledge Check
Answer each question one by one.
Q2Which method is the most natural fit for @classmethod?
Q3Which methods can be called without creating an instance? (Pick the most appropriate single answer if multiple apply.)