Menu
Coddy logo textTech

Static and Class Methods

Part of the Object Oriented Programming section of Coddy's Python journey — lesson 39 of 64.

Besides regular instance methods, classes can have static methods and class methods that serve different purposes.

Here is an example of a static method:

class MathHelper:
    @staticmethod
    def add(a, b):
        return a + b
    
    @staticmethod
    def is_even(number):
        return number % 2 == 0

Static methods don't need self and work like regular functions. Call them directly from the class:

result = MathHelper.add(5, 3)
print(result)

check = MathHelper.is_even(10)
print(check)

Here is an example of a class method:

class Person:
    count = 0  # Class variable
    
    def __init__(self, name):
        self.name = name
        Person.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count
    
    @classmethod
    def create_anonymous(cls):
        return cls("Anonymous")

Class methods receive the class itself (cls) as the first parameter:

person1 = Person("Alice")
person2 = Person("Bob")
print(Person.get_count())  # 2

Use class methods as alternative constructors:

anonymous = Person.create_anonymous()
print(anonymous.name)      # Anonymous
print(Person.get_count())  # 3

Compare all three method types in one class:

class Calculator:
    brand = "Python Calc"
    
    def __init__(self, owner):
        self.owner = owner
    
    # Instance method - needs self, accesses instance data
    def show_owner(self):
        return f"Owned by {self.owner}"
    
    # Class method - needs cls, accesses class data
    @classmethod
    def get_brand(cls):
        return cls.brand
    
    # Static method - needs neither, just a utility function
    @staticmethod
    def multiply(x, y):
        return x * y
calc = Calculator("Alice")
print(calc.show_owner())        # Owned by Alice
print(Calculator.get_brand())   # Python Calc
print(Calculator.multiply(4, 5)) # 20

Output:

8
True
2
Anonymous
3
Owned by Alice
Python Calc
20

You can call class and static methods from instances too:

calc = Calculator("Bob")
print(calc.get_brand())      # Python Calc
print(calc.multiply(2, 3))   # 6

Key Differences:

  • Instance methods: Need self, access instance data
  • Class methods: Need cls, access class data, good for alternative constructors
  • Static methods: Need neither, just utility functions related to the class

Key Point: Use @staticmethod for utility functions that belong logically to the class but don't need class or instance data. Use @classmethod when you need access to the class itself, like for alternative constructors or accessing class variables.

challenge icon

Challenge

Easy

In this challenge, you'll implement a Temperature class with specific functionality while leveraging a comprehensive testing framework.

You need to edit only the temperature.py file, following the TODO comments that guide your implementation. The class should include:

  • A class variable to track temperature readings
  • A static method for temperature conversion
  • Class methods for adding readings and calculating averages

Cheat sheet

Classes can have three types of methods: instance methods, static methods, and class methods.

Static methods use @staticmethod decorator, don't need self, and work like regular functions:

class MathHelper:
    @staticmethod
    def add(a, b):
        return a + b

# Call directly from class
result = MathHelper.add(5, 3)

Class methods use @classmethod decorator and receive the class (cls) as first parameter:

class Person:
    count = 0
    
    def __init__(self, name):
        self.name = name
        Person.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count
    
    @classmethod
    def create_anonymous(cls):
        return cls("Anonymous")

# Usage
print(Person.get_count())
anonymous = Person.create_anonymous()

Key differences:

  • Instance methods: Need self, access instance data
  • Class methods: Need cls, access class data, good for alternative constructors
  • Static methods: Need neither, just utility functions related to the class

Both class and static methods can be called from the class or from instances:

Calculator.multiply(4, 5)  # From class
calc.multiply(4, 5)        # From instance

Try it yourself

from temperature import Temperature

# Test case handler for comprehensive testing
test_case = input()

if test_case == "default_test":
    # Test basic functionality
    Temperature.celsius_readings = []
    Temperature.add_reading(25)
    Temperature.add_reading(30)
    Temperature.add_reading(27)
    
    print(f"Average reading: {Temperature.average_reading()}")
    print(f"22°C is {Temperature.celsius_to_fahrenheit(22)}°F")

elif test_case == "empty_readings":
    # Test average_reading with no readings
    Temperature.celsius_readings = []
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "single_reading":
    # Test with a single reading
    Temperature.celsius_readings = []
    Temperature.add_reading(100)
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "negative_values":
    # Test with negative temperature values
    Temperature.celsius_readings = []
    Temperature.add_reading(-10)
    Temperature.add_reading(-20)
    Temperature.add_reading(-30)
    print(f"Average reading: {Temperature.average_reading()}")
    print(f"-15°C is {Temperature.celsius_to_fahrenheit(-15)}°F")

elif test_case == "zero_value":
    # Test with a reading of 0°C
    print(f"0°C is {Temperature.celsius_to_fahrenheit(0)}°F")

elif test_case == "extreme_values":
    # Test with extreme temperature values
    absolute_zero = -273.15  # absolute zero in Celsius
    sun_surface = 5500  # approximate sun surface temperature in Celsius
    
    print(f"{absolute_zero}°C is {Temperature.celsius_to_fahrenheit(absolute_zero)}°F")
    print(f"{sun_surface}°C is {Temperature.celsius_to_fahrenheit(sun_surface)}°F")

elif test_case == "reset_readings":
    # Test resetting the readings
    Temperature.celsius_readings = []
    Temperature.add_reading(10)
    Temperature.add_reading(20)
    Temperature.add_reading(30)
    print(f"Average reading before reset: {Temperature.average_reading()}")
    
    Temperature.celsius_readings = []
    print(f"Average reading after reset: {Temperature.average_reading()}")

elif test_case == "decimal_values":
    # Test with decimal values
    Temperature.celsius_readings = []
    Temperature.add_reading(36.5)  # Normal body temperature
    Temperature.add_reading(37.2)  # Slight fever
    Temperature.add_reading(36.9)  # Normal variation
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "many_readings":
    # Test with many readings
    Temperature.celsius_readings = []
    for i in range(1, 101):
        Temperature.add_reading(i)
    print(f"Average reading with 100 values: {Temperature.average_reading()}")
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming