类方法是定义在类中的一种特殊方法,但它与类本身紧密相关。

一、类方法的定义

通过 @classmethod 装饰器定义类方法,它的第一个参数是 cls,代表类本身(而非实例):

class MyClass:
    # 类属性
    class_attr = "我是类属性"

    # 类方法:第一个参数是 cls
    @classmethod
    def class_func(cls, x):
        print(f"类方法中访问类属性:{cls.class_attr}")
        print(f"传入参数 x:{x}")
        # 可以通过 cls 创建实例、修改类属性等
        return cls()  # 返回一个新的实例

二、核心特点

  1. 参数是 clscls 是类本身的引用,类似于实例方法中的 self,但指向类而非实例;
  2. 可访问类属性:通过 cls 可以访问和修改类的属性(如 cls.class_attr);
  3. 不能访问实例属性:类方法不依赖于具体实例,因此无法通过 cls 访问实例独有的属性(如 self.instance_attr);
  4. 调用方式灵活:可通过「类名」或「实例名」调用(推荐用类名)。

三、调用方式

# 1. 通过类名调用(推荐,更清晰)
MyClass.class_func(10)

# 2. 通过实例名调用(也可行,但语义上不推荐)
obj = MyClass()
obj.class_func(20)

运行结果(两种调用方式输出一致):

类方法中访问类属性:我是类属性
传入参数 x:10
类方法中访问类属性:我是类属性
传入参数 x:20

四、适用场景

类方法的核心作用是操作类本身(而非实例),常见场景:

  1. 创建实例的替代构造函数:当需要多种方式创建实例时,类方法可以作为额外的 “构造函数”;
  2. 修改类属性:统一修改类的共享属性,影响所有实例;
  3. 类级别的工具函数:依赖类的状态(类属性),但不依赖实例状态的逻辑。
示例 1:替代构造函数

假设需要一个 Person 类,既可以通过 “姓名 + 年龄” 创建,也可以通过 “出生年份” 创建:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 类方法:通过出生年份创建实例(替代构造函数)
    @classmethod
    def from_birth_year(cls, name, birth_year):
        import datetime
        current_year = datetime.datetime.now().year
        age = current_year - birth_year
        return cls(name, age)  # 调用类的构造函数创建实例

# 两种创建实例的方式
p1 = Person("张三", 25)  # 直接调用 __init__
p2 = Person.from_birth_year("李四", 2000)  # 通过类方法创建

print(p1.age)  # 输出:25
print(p2.age)  # 输出:24(假设当前是2024年)
示例 2:修改类属性
class Counter:
    count = 0  # 类属性:记录实例总数

    def __init__(self):
        Counter.count += 1  # 每次创建实例,计数+1

    # 类方法:重置计数(修改类属性)
    @classmethod
    def reset(cls):
        cls.count = 0

# 创建实例
c1 = Counter()
c2 = Counter()
print(Counter.count)  # 输出:2

# 通过类方法重置计数
Counter.reset()
print(Counter.count)  # 输出:0

五、与实例方法、静态方法的区别

方法类型 装饰器 第一个参数 访问权限 核心用途
实例方法 self 类属性、实例属性都可访问 操作实例状态(如修改实例属性)
类方法 @classmethod cls 仅可访问类属性 操作类状态(如创建实例、修改类属性)
静态方法 @staticmethod 类属性、实例属性都不可访问 独立工具函数(仅依赖输入参数)
对比示例
class Student:
    school = "北京大学"  # 类属性

    def __init__(self, name):
        self.name = name  # 实例属性

    # 实例方法:依赖实例
    def show_name(self):
        print(f"学生姓名:{self.name}")

    # 类方法:依赖类
    @classmethod
    def change_school(cls, new_school):
        cls.school = new_school
        print(f"学校已修改为:{cls.school}")

    # 静态方法:无依赖
    @staticmethod
    def is_valid_name(name):
        return len(name) >= 2

# 调用对比
s1 = Student("张三")
s1.show_name()  # 实例方法:输出「学生姓名:张三」

Student.change_school("清华大学")  # 类方法:输出「学校已修改为:清华大学」
print(s1.school)  # 类属性已修改,输出「清华大学」

print(Student.is_valid_name("李四"))  # 静态方法:输出「True」

六、使用注意事项

  1. cls 不可修改cls 是类的引用,不能重新赋值(如 cls = OtherClass 无效);
  2. 避免访问实例属性:类方法不依赖实例,若强行通过 cls 访问实例属性(如 cls.name),会报错;
  3. 推荐用类名调用:类方法的语义是 “操作类”,用 类名.类方法() 调用更清晰(如 Person.from_birth_year());
  4. 与静态方法区分:若方法需要依赖类的状态(类属性),用类方法;若完全独立,用静态方法。

总结

类方法是 Python 中操作 “类本身” 的重要工具,核心价值是封装类级别的逻辑(如替代构造函数、修改类属性),同时通过 cls 参数保持对类的引用,确保代码的灵活性和可维护性。它与实例方法、静态方法各司其职,共同构成了 Python 类的完整方法体系。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐