Topic 8.3
Instance, Class and Static Methods
In one line
Python has three kinds of method. An instance method works on one object (self), a class method works on the class itself (cls) and is the standard way to write alternative constructors, and a static method is a plain function that lives inside a class for organisation.
Think of it like this
A pizza shop. Slicing this particular pizza needs that pizza in your hands: an instance method. Printing the menu is about the shop's recipe book, not one pizza: a class method. A sign reading "our sizes are 20 to 40 cm" does not need any pizza or recipe at all, it is just useful information kept next to the pizzas: a static method.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Instance method
- A method whose first parameter is
self. It works on one object. - Class method
- A method marked
@classmethodwhose first parameter iscls, the class. It works on the class. - Static method
- A method marked
@staticmethodthat receives neitherselfnorcls. It is a plain function stored in the class. - Decorator
- A line starting with
@above a function that wraps or changes it. Full details in Topic 9.6. - `cls`
- By convention, the name of the first parameter of a class method. It is the class the method was called on.
- Alternative constructor
- A class method that builds an object from some other starting data, such as text or a dictionary.
- Bound method
- A method looked up on an object. It remembers the object and passes it as
selfwhen called. - Factory
- A function or method whose job is to create and return objects.
Step by step
01The three kinds side by side
The class below has one of each. Read the first parameter of each: self, cls, and nothing. That first parameter tells you what the method can touch.
class Pizza:
def describe(self): # needs one pizza
...
@classmethod
def margherita(cls): # needs the class
...
@staticmethod
def is_valid_size(size): # needs neither
...02Instance methods use self
describe reads self.size and self.toppings. Without an object there is nothing to describe, so calling Pizza.describe() with no argument is an error: Python complains that self is missing.
03Class methods build objects
from_text takes text like "25:corn,onion", splits it and calls cls(size, toppings). You get a finished Pizza without anyone remembering the order of __init__ arguments.
A class can have as many of these as it needs, each with a clear name: from_text, from_dict, margherita. This is far clearer than one __init__ with many optional arguments.
@classmethod
def from_text(cls, text):
size, toppings = text.split(":")
return cls(int(size), toppings.split(","))04cls follows inheritance
When a subclass calls an inherited class method, cls is the subclass. That is why return cls(...) is right and return Message(...) is wrong. The first example in the code section shows LoudMessage.from_dict(raw) returning a LoudMessage with the louder behaviour built in.
05Static methods are plain functions
is_valid_size uses neither the object nor the class, so it is a static method. It can be called on the class or an instance with the same result.
Ask yourself: if this were a plain function in the module, would anything be worse? Often not. Choose a static method when keeping the function next to the class helps readers find it.
06What binding looks like
p1.describe is a bound method. Its __self__ is p1. Pizza.from_text.__self__ is the class Pizza. Pizza.describe(p1) calls the plain function stored on the class and passes the object yourself. (Python 3 has no separate "unbound method" type: looking up a method on the class just returns the function.) It gives the same answer as p1.describe().
Seeing these small facts removes the mystery: nothing magic happens, Python just supplies the first argument for you.
07Choosing between them
Ask what the method needs. One object's data: instance method. Only the class (to build objects or read class attributes): class method. Nothing: static method or a plain function. When in doubt, start with an instance method.
Try it yourself
- 1
Add a constructor
In the first example add
@classmethod def pepperoni(cls): return cls(35, ["pepperoni"])and printPizza.pepperoni().describe(). Predict the output first. - 2
Subclass it
Add
class BigPizza(Pizza): passand callBigPizza.margherita(). Printtype(...).__name__. It isBigPizza, becauseclsfollows the subclass. Now changemargheritatoreturn Pizza(30, ...)and run again to see what the hard-coded name loses. - 3
Call it three ways
Call
is_valid_size(25)on the class and on an object. Same answer. Then try callingdescribe()on the class with no argument and read the error.
Code & diagrams
Add a new alternative constructor, such as pepperoni(), that returns a 35 cm pizza with pepperoni.
Expected output
30cm pizza with ham
25cm pizza with corn, onion
30cm pizza with tomato, mozzarella
False True
method
True
True
TrueAI code constantly turns dictionaries from JSON into objects. Note that LoudMessage.from_dict returns a LoudMessage because it uses cls. The line super().__init__(...) in LoudMessage runs the parent class's setup; Topic 8.5 teaches it.
Expected output
Message('user', 'Hello')
Message('assistant', 'Hi there')
LoudMessage('assistant', 'HI THERE')
LoudMessage
{"role": "user", "content": "Hello"}Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Call an instance method on the class with no object
Write Pizza.describe() instead of Pizza.describe(p1) or p1.describe().
class Pizza:
@classmethod
def margherita(cls):
return cls()
def describe(self):
return "pizza"
print(Pizza.describe())Myth vs fact
Myth
Static methods are the same as plain functions, so they are always the right choice for helpers.
Fact
They behave like plain functions, but they travel with the class and can be overridden in subclasses. A module-level function is often simpler. Use a static method when the class is the natural home for it.
Myth
A class method is just a way to change class attributes.
Fact
That is one use. Its most common job is building objects (alternative constructors), because it receives the class and can call it.
Myth
cls and self are keywords.
Fact
Both are only naming conventions for the first parameter. The @classmethod decorator decides what is passed in, not the name.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
classmethod,staticmethodand plain functions are all descriptors: objects with a__get__method that Python calls during attribute lookup. A function's__get__returns a bound method, aclassmethod's returns a method bound to the class, andstaticmethod's returns the raw function. This is the whole mechanism. - ▸
Alternative constructors are better than overloading
__init__with many optional arguments or type checks. Python has no method overloading, sofrom_text,from_dictandfrom_filecommunicate intent and keep each signature honest. - ▸
Pydantic models use exactly this pattern:
Model.model_validate(data)is a class method that parses raw input, often an LLM's JSON, into a checked object. The standard library has the same idea indatetime.fromisoformat,dict.fromkeysandint.from_bytes. - ▸
Class methods should not be used to mutate global state through class attributes if a plain object would do. Shared mutable state on classes is hard to test and surprising in subclasses.
- ▸
Version note: Python 3.9 let you stack
@classmethodon top of@propertyto make class-level properties. That was deprecated in 3.11 and removed in 3.13, so code that relies on it breaks on current Python. Use a plain class method, or a custom descriptor, instead.
Remember this
- 1
An instance method is the normal kind. Its first parameter is
self, the object it was called on (Topic 8.1), so it can read and change that object's attributes. Use it whenever the behaviour depends on one object's data. - 2
A class method is marked with the decorator
@classmethod. A decorator is a line starting with@placed above a function that changes how the function behaves (Topic 9.6 explains how they work). A class method receives the class as its first parameter, namedclsby convention, instead of an object. It works the same whether you call it on the class or on an instance. - 3
The best use of class methods is alternative constructors: extra ways to build an object. Python has only one
__init__, soPizza.from_text("25:corn,onion")orMessage.from_dict(data)give you named ways to build objects from other shapes of data. They end withreturn cls(...). - 4
Writing
cls(...)instead of the class name matters. If a subclass inherits the class method,clsis the subclass, soLoudMessage.from_dict(raw)returns aLoudMessage. Hard-codingMessage(...)would always return aMessageand quietly break inheritance. - 5
A static method is marked
@staticmethodand receives neitherselfnorcls. It is an ordinary function that happens to be stored inside the class because it belongs to the topic, such asPizza.is_valid_size(size). If a function never uses the class or an object, a plain module-level function is often just as good. - 6
Under the hood, looking up an instance method on an object gives a bound method: a small object that remembers the instance and passes it as the first argument when called. A class method is bound to the class. A static method is returned unchanged. That is the entire difference.
Explain it without notes
What is the difference between an instance method, a class method and a static method?
Why write return cls(...) in a class method instead of return ClassName(...)?
What is an alternative constructor, and why does Python use class methods for them?
What is a bound method?
Practice
Write a class Temperature with attribute celsius, an instance method to_fahrenheit(), a class method from_fahrenheit(f) that builds one, and a static method is_freezing(c) that is true when c <= 0.
Write a class User with name and email, and a class method from_dict(data). Build a user from {"name": "Asha", "email": "a@x.com"} and print both attributes.
Make a subclass Admin(User) and show that Admin.from_dict(...) returns an Admin. Print the class name.
Trade-offs
- ↔
Class methods give clear, inheritable constructors, at the cost of one more concept. One
__init__plus named class methods is usually clearer than one__init__that guesses what you passed. - ↔
Static methods keep related helpers next to the class, but add little over a plain function. They help discoverability; they do not add power. Prefer a module-level function when the class is not a natural home.
Done when you can
Done when you can say what
selfandclsreceive and when to use each.Done when you can write an alternative constructor with
@classmethodandreturn cls(...).Done when you can explain why
clskeeps subclasses working.Done when you can decide whether a helper should be an instance, class or static method.
Done when you can explain what a bound method is.