Hiprup

What are class methods, static methods, and instance methods?

Python classes support three styles of callable members. They differ in what (if anything) gets passed implicitly as the first argument.

  • Instance method — the default. Receives the instance as self. Operates on per-object state.

  • Class method — decorated with @classmethod. Receives the class as cls. Operates on the class itself or builds instances via alternative constructors.

  • Static method — decorated with @staticmethod. Receives nothing implicit. Logically belongs to the class but doesn’t use self or cls.

Example:

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

    def describe(self):                # instance method
        return f"pizza with {self.toppings}"

    @classmethod
    def margherita(cls):               # class method — alternative constructor
        return cls(["tomato", "mozzarella", "basil"])

    @staticmethod
    def is_vegetarian(toppings):       # static method — pure helper
        return all(t not in {"pepperoni", "bacon"} for t in toppings)

p = Pizza.margherita()                # uses classmethod constructor
p.describe()                          # instance method
Pizza.is_vegetarian(["mushroom"])    # static helper

class Employee:
    raise_percentage = 1.05  # Class variable
    _count = 0

    def __init__(self, name, salary):
        self.name = name
        self.salary = salary
        Employee._count += 1

    # Instance method - accesses instance data
    def apply_raise(self):
        self.salary *= self.raise_percentage

    # Class method - accesses class data, alternative constructor
    @classmethod
    def set_raise_percentage(cls, percentage):
        cls.raise_percentage = percentage

    @classmethod
    def from_string(cls, emp_str):  # Alternative constructor
        name, salary = emp_str.split(',')
        return cls(name.strip(), float(salary.strip()))

    @classmethod
    def get_count(cls):
        return cls._count

    # Static method - utility, no access to class/instance
    @staticmethod
    def is_valid_salary(salary):
        return salary > 0

# Usage
emp = Employee('John', 50000)
emp.apply_raise()                          # Instance method
print(emp.salary)                           # 52500.0

Employee.set_raise_percentage(1.10)          # Class method
emp2 = Employee.from_string('Jane, 60000')  # Alternative constructor
print(Employee.get_count())                  # 2

print(Employee.is_valid_salary(-100))        # Static method: False

apply_raise uses self to modify the instance's salary. set_raise_percentage uses cls to modify the class variable for all instances. from_string is a factory method — it creates an Employee from a different format (string instead of separate arguments). is_valid_salary is a utility that does not need self or cls — it is just a function scoped to the class.

The factory method pattern (from_string) is the most practical use of @classmethod. Know that @staticmethod is just a namespaced function — no access to self or cls.

The self vs cls distinction (instance vs class access) is the core concept.

What are class methods, static methods, and instance methods? | Hiprup