Menu
CoddyTech

静态方法与类方法

本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 39 课,共 64 课。

除了常规的实例方法,类还可以有静态方法和类方法,它们的用途各不相同。

下面是一个静态方法的示例:

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

静态方法不需要 self,其工作方式与普通函数相同。直接通过类调用它们:

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

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

下面是一个类方法的示例:

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")

类方法会将类本身(cls)作为第一个参数接收:

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

使用类方法作为替代构造函数:

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

在一个类中比较这三种方法:

class Calculator:
    brand = "Python Calc"
    
    def __init__(self, owner):
        self.owner = owner
    
    # 实例方法:需要 self,可访问实例数据
    def show_owner(self):
        return f"Owned by {self.owner}"
    
    # 类方法:需要 cls,可访问类数据
    @classmethod
    def get_brand(cls):
        return cls.brand
    
    # 静态方法:两者都不需要,只是一个工具函数
    @staticmethod
    def multiply(x, y):
        return x * y
calc = Calculator("Alice")
print(calc.show_owner())        # 归 Alice 所有
print(Calculator.get_brand())   # Python Calc
print(Calculator.multiply(4, 5)) # 20

输出:

8
True
2
Anonymous
3
Owned by Alice
Python Calc
20

你也可以通过实例调用类方法和静态方法:

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

主要区别:

  • 实例方法:需要 self,可以访问实例数据
  • 类方法:需要 cls,可以访问类数据,适合用作替代构造函数
  • 静态方法:两者都不需要,只是与类相关的实用函数

关键点:对于逻辑上属于类、但不需要类或实例数据的实用函数,使用 @staticmethod。当你需要访问类本身时,例如创建替代构造函数或访问类变量,则使用 @classmethod。

challenge icon

挑战

简单

在这个挑战中,你将实现一个具有特定功能的 Temperature 类,并使用全面的测试框架。

你只需要编辑 temperature.py 文件,并按照指导你完成实现的 TODO 注释操作。这个类应包含:

  • 一个用于跟踪温度读数的类变量
  • 一个用于温度转换的静态方法
  • 用于添加读数和计算平均值的类方法

亲手试试

from temperature import Temperature

# 用于全面测试的测试用例处理程序
test_case = input()

if test_case == "default_test":
    # 测试基本功能
    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":
    # 测试没有读数时的 average_reading
    Temperature.celsius_readings = []
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "single_reading":
    # 使用单个读数进行测试
    Temperature.celsius_readings = []
    Temperature.add_reading(100)
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "negative_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":
    # 使用 0°C 的读数进行测试
    print(f"0°C is {Temperature.celsius_to_fahrenheit(0)}°F")

elif test_case == "extreme_values":
    # 使用极端温度值进行测试
    absolute_zero = -273.15  # 以摄氏度表示的绝对零度
    sun_surface = 5500  # 以摄氏度表示的太阳表面近似温度
    
    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":
    # 测试重置读数
    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":
    # 使用小数值进行测试
    Temperature.celsius_readings = []
    Temperature.add_reading(36.5)  # 正常体温
    Temperature.add_reading(37.2)  # 轻微发烧
    Temperature.add_reading(36.9)  # 正常波动
    print(f"Average reading: {Temperature.average_reading()}")

elif test_case == "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 icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Python 在线编译器