HOWTO · Python
Class Methods in Python
This tutorial discusses class methods in Python.
On this page
A class is a blueprint for objects, but it can also hold data and behavior shared by every object it creates. Python offers instance methods, class methods, and static methods so that code can express which of those places it needs to work with.
An instance method receives an instance as its first argument, conventionally named self. Use it when the operation needs data from one particular object, such as an employee’s name or age. A class method instead receives the class object as its first argument, conventionally named cls. It can be called through the class without first creating an instance, and it can read or update class-level state.
The value passed as cls is the actual class used for the call, not an arbitrary instance. That detail makes class methods especially useful for alternative constructors: a method can validate input and return cls(...), allowing a subclass to receive an instance of itself. A static method receives neither self nor cls; it is a namespaced utility that happens to live in the class.
Python provides two supported ways to create a class method: convert an existing function with classmethod(), or use the @classmethod decorator. The decorator is usually clearer in new code because the method’s binding is visible where it is defined. The conversion form remains useful when maintaining code that already has a plain function.
Use the classmethod() Function to Create a Class Method in Python
The classmethod() function accepts a function and returns a class-method descriptor. Define the function in the class, then assign the converted descriptor back to the attribute. In this example, department_name receives Emp as cls, so it can obtain the shared department attribute when called as Emp.department_name().
class Emp:
department = "Python"
def department_name(cls):
print(f"Department: {cls.department}")
Emp.department_name = classmethod(Emp.department_name)
Emp.department_name()
Output:
Department: Python
This conversion does not make classmethod() obsolete; it is a valid way to adapt an existing method. For new definitions, however, the decorator form below is easier to scan and avoids separating the function definition from its conversion. In either form, call the method through the class when its purpose is class-level configuration, construction, or other behavior that does not depend on one object.
Use the @classmethod Decorator to Create a Class Method in Python
Place @classmethod immediately above a method definition to bind its first parameter to the class. The parameter name is a convention rather than a language requirement, but cls makes the method’s role clear. The method can use cls to access class attributes, call other class methods, or construct a new object without hard-coding the base class name.
Here is the same class-level lookup using the preferred decorator form:
class Emp:
department = "Python"
@classmethod
def department_name(cls):
print(f"Department: {cls.department}")
Emp.department_name()
Output:
Department: Python
Class methods are inherited. Crucially, a call such as Manager.from_record(...) binds cls to Manager, even when the method was defined on a parent class. That is why a factory should return cls(...) instead of Employee(...): the latter would always create the parent type. Python does not implement same-name method overloading by selecting a method from argument types; use distinct method names, optional arguments, or a class method such as a named alternative constructor when those better describe the API.
The following factory parses a simple record, converts the age to an integer, and returns the calling class. It is a success case because the input contains exactly two non-empty comma-separated fields.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_record(cls, record):
name, age_text = record.split(",")
return cls(name, int(age_text))
employee = Employee.from_record("Matt,15")
print(f"{employee.name}: {employee.age}")
Output:
Matt: 15
The from_record() method returns an Employee object because cls is Employee for this call. A subclass can reuse the method without rewriting the parsing logic. For example, class Manager(Employee): pass followed by Manager.from_record("Ava,30") creates a Manager, because cls then refers to Manager.
Input validation belongs at the boundary where external text becomes structured data. split(",") can produce the wrong number of fields, and int() can reject a non-numeric age. Raise a clear ValueError so callers can handle malformed records deliberately instead of receiving an object with unreliable state. The following boundary case catches that error and prints a predictable message.
class Employee:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_record(cls, record):
parts = record.split(",")
if len(parts) != 2 or not all(part.strip() for part in parts):
raise ValueError("record must contain a name and age")
name, age_text = parts
try:
return cls(name.strip(), int(age_text))
except ValueError as error:
raise ValueError("age must be an integer") from error
# boundary case: a record without an age is rejected
try:
Employee.from_record("Matt,")
except ValueError as error:
print(f"Invalid record: {error}")
Output:
Invalid record: record must contain a name and age
Choose an instance method when behavior needs one object’s state, such as updating self.age. Choose a class method when it needs class-wide state or must create the class that received the call. Choose a static method when the logic belongs conceptually with the class but needs neither an instance nor class state. Static methods can still be called through the class, but they cannot automatically inspect or modify class attributes because Python passes no cls argument to them. This distinction keeps APIs direct and makes each method’s dependencies visible to readers and maintainers.