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 == 0Static 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()) # 2Use class methods as alternative constructors:
anonymous = Person.create_anonymous()
print(anonymous.name) # Anonymous
print(Person.get_count()) # 3Compare 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 * ycalc = Calculator("Alice")
print(calc.show_owner()) # Owned by Alice
print(Calculator.get_brand()) # Python Calc
print(Calculator.multiply(4, 5)) # 20Output:
8
True
2
Anonymous
3
Owned by Alice
Python Calc
20You can call class and static methods from instances too:
calc = Calculator("Bob")
print(calc.get_brand()) # Python Calc
print(calc.multiply(2, 3)) # 6Key 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
EasyIn 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 instanceTry 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()}")This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe self ParameterMethodsAttributesConstructor Method (__init__)Recap - Simple Calculator4Inheritance
Basic InheritanceThe super() FunctionMethod OverridingMultiple InheritanceMethod Resolution OrderRecap - Employee Hierarchy7Special Methods
Magic Methods IntroductionOperator OverloadingContainer Magic MethodsRecap - Custom List10Design Patterns Part 1
Intro to design patternSingleton PatternFactory PatternObserver PatternStrategy Pattern2Decorators
Introduction to DecoratorsProperty DecoratorStatic Method DecoratorClass Method Decorator5Polymorphism
Method Overriding RevisitedDuck TypingAbstract Classes and MethodsInterface DesignRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceMixinsStatic and Class MethodsClass DecoratorsContext Managers3Class Properties
Instance vs Class VariablesProperty DecoratorsPrivate AttributesRecap - Bank Account Manager6Encapsulation
Public, Protected, Private MemAccess ModifiersInformation HidingProperty Decorators AdvancedRecap - Student Records System12Project: Library Management
Project OverviewBook and User Classes