当前位置:首页>python>【python进阶】使用@classmethod 支持多态构造

【python进阶】使用@classmethod 支持多态构造

  • 2026-10-11 08:00:42
【python进阶】使用@classmethod 支持多态构造

@classmethod是 Python 的内置装饰器,用来定义类方法。

类方法的特点是:调用时,第一个参数不是实例 self,而是类本身 cls。

1. 普通实例方法

普通方法第一个参数是self:

pythoninstance method

class User:    def hello(self):        print(self)

调用:

u = User()u.hello()

实际等价于:

User.hello(u)

所以self是实例对象。

2. 类方法 @classmethod

类方法第一个参数通常写成cls:

class User:    @classmethod    def create(cls):        print(cls)        return cls()

调用:

u = User.create()

实际等价于:

User.create()// Python 自动把 User 传给 cls

所以:

cls == User

3. 最小例子

class A:    @classmethod    def show_class(cls):        print(cls)A.show_class()

输出类似:

<class '__main__.A、、、、 

也就是说,cls拿到的是类对象A。

4. 和 self 的区别

class A:    def instance_method(self):        print("self =", self)    @classmethod    def class_method(cls):        print("cls =", cls)a = A()a.instance_method()A.class_method()

输出概念上:

self = <__main__.A object at 0x...>cls = <class '__main__.A'>

区别是:

方法类型
第一个参数
表示什么
普通方法
self
实例对象
类方法
cls
类对象

5. @classmethod 常见用途:替代构造函数

最常见用途是写“命名构造器”。

比如:

class User:    def __init__(self, name: str, age: int):        self.name = name        self.age = age    @classmethod    def from_dict(cls, data: dict):        return cls(            name=data["name"],            age=data["age"],        )

使用:

user = User.from_dict({    "name": "Alice",    "age": 18})

等价于:

user = User("Alice", 18)

但是from_dict的语义更清楚。

6. 为什么不用 staticmethod

如果写成普通函数也能创建对象:

class User:    @staticmethod    def from_dict(data):        return User(data["name"], data["age"])

但这里硬编码了User。

如果以后有子类:

class Admin(User):    pass

调用:

Admin.from_dict({"name": "Bob", "age": 20})

staticmethod 版本

返回的是:

User(...)

classmethod 版本

返回的是:

Admin(...)
cls == Admin
这就是 @classmethod 的优势:支持继承和多态构造。

7. 继承例子

class User:    def __init__(self, name):        self.name = name    @classmethod    def from_name(cls, name):        return cls(name)class Admin(User):    passu = User.from_name("Alice")a = Admin.from_name("Bob")print(type(u))print(type(a))

输出:

<class '__main__.User'><class '__main__.Admin'>

因为:

User.from_name("Alice")  cls = UserAdmin.from_name("Bob")   cls = Admin

总结

@classmethod 的优势在于它将类本身(cls)作为参数传递,从而解耦了类名与构造逻辑。这使得设计模式中的“工厂方法(Factory Method)”在面对类继承时,能够保持完美的灵活性和可扩展性。

最新文章

随机文章