Python 支持三种类型的类方法:实例方法、类方法和静态方法。它们在调用方式和对类及实例数据的访问上有所不同。
历史:
最初,类方法(带有 "self" 的那些)是唯一的行为类型,暗示方法总是调用特定对象的行为或更改/读取特定对象的数据。后来 Python 引入了类方法(带有 "cls"),为整个类提供行为(例如,替代构造函数),以及与普通函数相似的静态方法,但与类相关。
问题:
有时需要所有实例的公共功能(静态方法)。有时操作需要对 "整个类" 可用(例如,创建实例)。在这种情况下,如果方法类型定义不正确,可能会导致错误(例如,偶然尝试通过实例方法更改类,或反之亦然)。
解决方案:
代码示例:
class MyClass: def instance_method(self): return f"实例:{self}" @classmethod def class_method(cls): return f"类:{cls}" @staticmethod def static_method(): return "这是一个静态方法" obj = MyClass() print(obj.instance_method()) # 实例:<MyClass object...> print(MyClass.class_method()) # 类:<class 'MyClass'> print(MyClass.static_method())# 这是一个静态方法
关键特性:
可以直接通过类调用实例方法吗?
可以,但需要显式传递对象:
MyClass.instance_method(obj)
这样做很少合适。
静态方法在继承时的行为:可以被重写吗?
可以,可以在子类中以相同的名称声明 staticmethod,并且在从子类调用时将调用该方法。
如果总是可以使用带有 cls 作为参数的静态方法,为什么要使用类方法?
cls 不仅仅是第一个参数:在 classmethod 中,Python 会自动将相应的类作为 cls 插入,即使调用是从子类进行的。这允许在没有严格绑定到父类的情况下创建替代构造函数层次。
示例:
class Base: @classmethod def make(cls): return cls() class Child(Base): pass Child.make() # 将返回 Child,而不是 Base
在项目中使用普通方法创建替代实例(例如,create_from_json)。因此,在继承时,该方法始终返回基类对象,而不是子类对象。
优点:
缺点:
实现了 classmethod 工厂,即使从子类调用也会返回当前类的实例 (cls())。
优点:
缺点: