ZetCode

Python classmethod 函数

上次修改时间:2025 年 4 月 11 日

这份综合指南探讨了 Python 的 classmethod 装饰器,它将一个方法转换为一个类方法。我们将涵盖面向对象编程中类方法的定义、用例和实践示例。

基本定义

classmethod 是一个内置函数装饰器,它将一个方法转换为类方法。类方法接收类作为隐式第一个参数,就像实例方法接收实例一样。

主要特点:绑定到类而不是实例,可以修改类状态,通常用于替代构造函数和工厂方法。使用 @classmethod 装饰器语法定义。

基本 classmethod 用法

这是一个简单的例子,展示了如何定义和使用类方法,并将其与常规实例方法进行比较。

basic_classmethod.py
class MyClass:
    def instance_method(self):
        print(f"Called instance_method of {self}")
    
    @classmethod
    def class_method(cls):
        print(f"Called class_method of {cls}")

# Instance method requires an instance
obj = MyClass()
obj.instance_method()  # Called instance_method of <__main__.MyClass object>

# Class method can be called on the class
MyClass.class_method()  # Called class_method of <class '__main__.MyClass'>

此示例演示了实例方法和类方法之间的根本区别。 类方法接收类 (cls) 作为其第一个参数,而不是实例 (self)。

类方法可以在类本身和实例上调用,而实例方法只能在实例上调用。

替代构造函数

类方法的常见用例是创建替代构造函数。 此示例演示了如何从不同的数据格式创建对象。

alternative_constructor.py
class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
    
    @classmethod
    def from_string(cls, date_string):
        year, month, day = map(int, date_string.split('-'))
        return cls(year, month, day)
    
    @classmethod
    def from_dict(cls, date_dict):
        return cls(date_dict['year'], date_dict['month'], date_dict['day'])
    
    def __repr__(self):
        return f"Date({self.year}, {self.month}, {self.day})"

# Using standard constructor
d1 = Date(2025, 4, 11)

# Using alternative constructors
d2 = Date.from_string("2025-04-11")
d3 = Date.from_dict({'year': 2025, 'month': 4, 'day': 11})

print(d1)  # Date(2025, 4, 11)
print(d2)  # Date(2025, 4, 11)
print(d3)  # Date(2025, 4, 11)

此 Date 类提供了两个作为类方法的替代构造函数。 from_string 方法解析日期字符串,而 from_dict 从字典创建 Date。

cls 参数引用类本身,允许这些方法创建新实例。 这种模式在 Python 标准库中很常见(例如,datetime.datetime.fromtimestamp)。

类状态修改

类方法可以修改影响所有实例的类级别状态。 此示例演示了跟踪实例计数。

class_state.py
class Counter:
    count = 0
    
    def __init__(self):
        self.increment()
    
    @classmethod
    def increment(cls):
        cls.count += 1
    
    @classmethod
    def get_count(cls):
        return cls.count
    
    @classmethod
    def reset(cls):
        cls.count = 0

# Create instances
c1 = Counter()
c2 = Counter()
c3 = Counter()

print(Counter.get_count())  # 3

Counter.reset()
print(Counter.get_count())  # 0

Counter 类使用类方法来管理类级别的状态。 count 变量在所有实例之间共享,类方法提供对它的受控访问以进行修改。

这种模式对于维护共享状态、配置或跨整个类层次结构跟踪实例非常有用。

继承行为

类方法可以正确地与继承一起使用,接收最派生的类作为它们的第一个参数。 此示例演示了多态类方法。

inheritance.py
class Animal:
    @classmethod
    def make_sound(cls):
        return f"{cls.__name__} makes a generic sound"

class Dog(Animal):
    @classmethod
    def make_sound(cls):
        return f"{cls.__name__} barks"

class Cat(Animal):
    pass

print(Animal.make_sound())  # Animal makes a generic sound
print(Dog.make_sound())     # Dog barks
print(Cat.make_sound())     # Cat makes a generic sound

此示例演示了类方法如何支持继承。 当在子类上调用时,子类作为 cls 传递,从而允许进行多态行为。

Cat 类继承父类的类方法,而 Dog 类覆盖它。 这演示了如何在子类中专门化类方法。

工厂模式

类方法通常用于实现工厂模式,根据输入创建不同类型的对象。 此示例显示了一个形状工厂。

factory.py
class Shape:
    def draw(self):
        pass
    
    @classmethod
    def create_shape(cls, shape_type):
        if shape_type == "circle":
            return Circle()
        elif shape_type == "square":
            return Square()
        else:
            raise ValueError(f"Unknown shape type: {shape_type}")

class Circle(Shape):
    def draw(self):
        print("Drawing a circle")

class Square(Shape):
    def draw(self):
        print("Drawing a square")

# Using the factory method
circle = Shape.create_shape("circle")
square = Shape.create_shape("square")

circle.draw()  # Drawing a circle
square.draw()  # Drawing a square

create_shape 类方法充当工厂,根据输入参数创建不同的 Shape 子类。 这将对象创建逻辑封装在一个地方。

当要实例化的确切类在运行时才知道,或者需要根据配置或输入动态确定时,此模式非常有用。

最佳实践

资料来源

作者

我的名字是 Jan Bodnar,我是一位充满激情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程