Python Class Methods
Object-Oriented Python Object-Oriented Python

Python Class Methods and Static Methods

1Python Class Methods: overview

A class method receives the class itself (cls) instead of one object, which makes it ideal for alternative constructors and class-level state, while a static method receives nothing automatically and is just a plain function filed inside the class.

GoalBy the end you can tell instance, class and static methods apart, write alternative constructors with @classmethod and cls, update class-level state from a class method, call all three kinds through the class and through an object, and decide when a plain function is better.

Before this lesson: Python Classes and Objects, Python Class Attributes vs Instance Attributes

2Python Class Methods: diagram

Three kinds of methodThree kinds of methodkindfirst paraminstance dataclass datatypical useinstance methodselfyesyeswork with one object@classmethodclsnoyesalternative constructors@staticmethod(none)nonohelper kept in the classThe first parameter is what Python passes in for you. A static method only sees its own arguments.
The three kinds of method differ in what Python hands them automatically as the first argument: the object, the class, or nothing at all. That decides which data each kind can reach without help.

3Python Class Methods: explained step by step

So far every method you have written starts with self, which means it works on one particular object. That covers most needs, but two situations keep coming up:

  • You want a method that belongs to the class as a whole, such as a new way to create objects or an update to a class-level counter. At that moment there may be no object to call it on.
  • You have a helper function that is clearly about the class but never touches any object's data.

Python has a kind of method for each: class methods and static methods. You create them with a decorator, a line starting with @ placed directly above the def, which tells Python to treat the method differently.

Three kinds of method

The diagram above compares them. The real difference is what Python passes in automatically as the first argument: the object (instance method), the class (class method), or nothing (static method). That decides what data each kind can reach.

Class methods and cls

Put @classmethod above a method and name its first parameter cls. Python then passes the class itself instead of an object. With cls you can read class attributes and, most usefully, create objects: cls(...) does the same as calling the class by name.

Python
class Pizza:
    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings

    @classmethod
    def from_string(cls, text):
        inches, toppings = text.split(":")
        return cls(int(inches), toppings.split(","))

    def describe(self):
        return f"{self.inches}-inch pizza with {', '.join(self.toppings)}"

order = Pizza.from_string("12:ham,olives,corn")
print(order.describe())

You call it on the class, Pizza.from_string(...), and no pizza has to exist yet. Inside, cls is Pizza, so cls(...) builds a new pizza. Writing cls instead of the literal class name keeps the method correct if the class is renamed or extended later.

Alternative constructors

A class gets only one __init__. Class methods fill the gap: each one is a named "door" into creating an object, usually called from_something. The caller picks the door that matches the data they have.

Python
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day

    @classmethod
    def from_string(cls, text):        # build from text like "2024-12-25"
        year, month, day = text.split("-")
        return cls(int(year), int(month), int(day))

    @classmethod
    def new_year(cls, year):           # build from fixed data: always 1 January
        return cls(year, 1, 1)

    def __str__(self):
        return f"{self.day:02d}/{self.month:02d}/{self.year}"

print(Date(2025, 3, 14))
print(Date.from_string("2024-12-25"))
print(Date.new_year(2026))

Every door ends in cls(...), so all objects are still set up by the same __init__. That keeps the rules for a valid object in one place.

Class methods and class-level state

Because cls is the class, cls.count = 0 changes the class attribute that every object shares. (Doing the same through self would only create an instance attribute that hides it, as you saw in the previous lesson.)

Python
class Player:
    count = 0

    def __init__(self, name):
        self.name = name
        Player.count += 1

    @classmethod
    def how_many(cls):
        return f"{cls.count} players created"

    @classmethod
    def reset_count(cls):
        cls.count = 0

Player("Asha")
Player("Ben")
print(Player.how_many())
Player.reset_count()
print(Player.how_many())

Static methods

Sometimes a function is closely related to a class but needs neither an object nor the class itself. @staticmethod stores such a function inside the class. Python passes no automatic first argument, so you write exactly the parameters you want. A static method is a plain function that happens to live in the class's namespace, which keeps related code together and ties the name to the class.

Python
class Temperature:
    @staticmethod
    def celsius_to_fahrenheit(celsius):
        return celsius * 9 / 5 + 32

print(Temperature.celsius_to_fahrenheit(100))
reading = Temperature()
print(reading.celsius_to_fahrenheit(0))

Calling all three kinds

Each kind can be called through the class or through an object, but they do not behave identically. An instance method called through the class needs the object handed over by hand. Class and static methods work the same either way.

Python
class Cafe:
    drinks_sold = 0

    def __init__(self, name):
        self.name = name

    def sell(self):                    # instance method: needs one cafe
        Cafe.drinks_sold += 1
        return f"{self.name} sold a drink"

    @classmethod
    def total_sold(cls):               # class method: receives the class
        return cls.drinks_sold

    @staticmethod
    def is_open(hour):                 # static method: receives nothing extra
        return 8 <= hour < 18

harbor = Cafe("Harbor Cafe")
print(harbor.sell())
print(Cafe.sell(harbor))               # through the class: pass the object yourself
print(Cafe.total_sold(), harbor.total_sold())
print(Cafe.is_open(9), harbor.is_open(20))

Cafe.sell(harbor) is exactly what harbor.sell() does behind the scenes.

Which kind do I need?

  • It uses the data of one object (self.something)? Write an instance method.
  • It needs the class, either to create objects or to read and change class attributes, but not one particular object? Write a class method.
  • It needs neither? It might be a static method, but read the next section first.

When not to use a static method

In Python a function does not have to live inside a class. If it needs neither an object nor the class, a plain module-level function is often the simplest choice:

def celsius_to_fahrenheit(celsius):
    return celsius * 9 / 5 + 32

Choose a static method when the function is really part of the class's idea and you want it found next to the related code, like Pizza.inches_to_cm(12). A class that holds nothing but static methods and is never instantiated is just a module in disguise.

Quick reference: Python Class Methods

4Python Class Methods: syntax

class ClassName:
    shared = 0                        # class attribute

    def __init__(self, a):
        self.a = a

    def instance_method(self):        # first parameter: the object
        return self.a

    @classmethod
    def from_text(cls, text):         # first parameter: the class
        return cls(int(text))         # build and return a new object

    @staticmethod
    def helper(x):                    # no self, no cls
        return x * 2

obj = ClassName.from_text("5")        # class method: call it on the class
obj.instance_method()                 # instance method: call it on an object
ClassName.helper(4)                   # static method: through the class ...
obj.helper(4)                         # ... or through an object

5Python Class Methods: run the example

Press Run (or Ctrl + Enter). The output (step 6) appears directly below the code. Change anything and run it again.

Interactive example
class Pizza:
    made = 0

    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings
        Pizza.made += 1

    @classmethod
    def from_string(cls, text):
        inches, toppings = text.split(":")
        return cls(int(inches), toppings.split(","))

    @staticmethod
    def inches_to_cm(inches):
        return round(inches * 2.54, 1)

    def __str__(self):
        return f"{self.inches}-inch pizza with {', '.join(self.toppings)}"

order = Pizza.from_string("12:ham,olives")
print(order)
print(Pizza.inches_to_cm(order.inches), "cm")
print("Pizzas made:", Pizza.made)
Expected output12-inch pizza with ham, olives
30.5 cm
Pizzas made: 1

7Python Class Methods: how the example works

Hover or tap a step to highlight its lines in the example above.

  1. Line 1-2made is a class attribute: one shared counter for the whole Pizza class.
  2. Line 4-7__init__ is a normal instance method. It stores the size and toppings on self and adds one to the shared counter through the class name.
  3. Line 9-12@classmethod makes from_string receive the class as cls. It splits "12:ham,olives" into the size and the toppings, converts the size to a number, and returns cls(...), so the new pizza is built by __init__ like any other.
  4. Line 14-16@staticmethod makes inches_to_cm a plain function stored in the class. It gets only the argument you pass and cannot see self or cls.
  5. Line 18-19__str__ is an instance method that describes one pizza. It uses self.inches and self.toppings.
  6. Line 21Pizza.from_string(...) is called on the class because no pizza exists yet. It returns a new Pizza object, which is stored in order.
  7. Line 22print(order) calls __str__ and shows 12-inch pizza with ham, olives.
  8. Line 23The static method is also called on the class. 12 inches is 30.48 cm, rounded to 30.5.
  9. Line 24Only one pizza was built, through from_string and then __init__, so the counter reads 1.

8Python Class Methods: common mistakes

Forgetting @classmethod

✗ Wrong

class Pizza:
    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings

    def from_string(cls, text):
        inches, toppings = text.split(":")
        return cls(int(inches), toppings.split(","))

order = Pizza.from_string("12:ham,olives")
TypeError: Pizza.from_string() missing 1 required positional argument: 'text'

✓ Right

class Pizza:
    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings

    @classmethod
    def from_string(cls, text):
        inches, toppings = text.split(":")
        return cls(int(inches), toppings.split(","))

order = Pizza.from_string("12:ham,olives")
print(order.inches, order.toppings)

Without the decorator, from_string is a plain function: the string you pass lands in cls and nothing is left for text. Add @classmethod above the def so Python passes the class automatically.

A helper without @staticmethod called on an object

✗ Wrong

class Converter:
    def km_to_miles(km):
        return km * 0.621371

trip = Converter()
print(trip.km_to_miles(10))
TypeError: Converter.km_to_miles() takes 1 positional argument but 2 were given

✓ Right

class Converter:
    @staticmethod
    def km_to_miles(km):
        return km * 0.621371

trip = Converter()
print(trip.km_to_miles(10))

Called on an object, a normal method receives that object as an extra first argument. Mark the helper with @staticmethod so Python passes nothing extra.

Reading instance data inside a class method

✗ Wrong

class Player:
    def __init__(self, name):
        self.name = name

    @classmethod
    def greet(cls):
        return f"Hello, {cls.name}"

print(Player("Asha").greet())
AttributeError: type object 'Player' has no attribute 'name'

✓ Right

class Player:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Hello, {self.name}"

print(Player("Asha").greet())

A class method receives the class, and name belongs to individual objects, so the class has no name. If the method needs one player's data, make it a normal instance method that uses self.

An alternative constructor that forgets to return

✗ Wrong

class Pizza:
    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings

    @classmethod
    def from_string(cls, text):
        inches, toppings = text.split(":")
        cls(int(inches), toppings.split(","))

order = Pizza.from_string("12:ham,olives")
print(order.inches)
AttributeError: 'NoneType' object has no attribute 'inches'

✓ Right

class Pizza:
    def __init__(self, inches, toppings):
        self.inches = inches
        self.toppings = toppings

    @classmethod
    def from_string(cls, text):
        inches, toppings = text.split(":")
        return cls(int(inches), toppings.split(","))

order = Pizza.from_string("12:ham,olives")
print(order.inches)

The method built a pizza but threw it away, so the call returned None. A factory method must return the object it creates.

9Python Class Methods: exercises

Write your answer, then press Check. The checks run in your browser.

1. A square factory

Write code Easy

Add a class method square(cls, side) to Rectangle. It must return a new Rectangle whose width and height are both side. Build the object with cls(...).

Your code
class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

    # add a class method square(cls, side) here

print(Rectangle(3, 4).area())

2. Predict the three method kinds

Predict the output Medium

This class uses an instance method, a class method and a static method. Type exactly what the program prints.

Read this code
class Gym:
    members = 0

    def __init__(self, name):
        self.name = name
        Gym.members += 1

    @classmethod
    def count(cls):
        return cls.members

    @staticmethod
    def hours():
        return "6am-10pm"

    def welcome(self):
        return f"Welcome, {self.name}! ({Gym.count()} members)"

a = Gym("Asha")
b = Gym("Ben")
print(a.welcome())
print(Gym.count(), b.count(), Gym.hours())
print(Gym.welcome(b))

2 more exercises → 6 more examples

Finished this lesson?
Progress is saved in this browser — create a free account to keep it across devices.

Questions learners ask

What is the difference between @classmethod and @staticmethod?

A class method receives the class as its first argument (cls), so it can read and change class attributes and create new objects with cls(...). A static method receives no automatic argument at all; it is an ordinary function stored inside the class. Neither one receives an object (self).

How do I write more than one constructor in Python?

A class can have only one init, so add alternative constructors as class methods, usually named from_something, such as Pizza.from_string(...) or Date.from_string(...). Each one prepares the data and ends with return cls(...), so the object is still built by init.

Should I use a static method or a normal function?

Python does not force you to put functions inside classes. If the function needs neither self nor cls, a plain module-level function is usually simpler. Use a static method only when the function is clearly part of the class's idea and you want it kept next to the related code, for example Pizza.inches_to_cm().

Further reading

10Next lesson

Up nextPython Encapsulation: Public, Protected and PrivateEncapsulation means keeping an object's data behind a small set of public methods that check every change, so the objec…

Related:
Python FunctionsPython Class Attributes vs Instance AttributesPython Dunder (Magic) Methods

← Python Class Attributes vs Instance Attributes · All Object-Oriented Python lessons · Practise in the IDE