为什么Python中class变量全局共享,classmethod却每个实例单独创建?
类变量与classmethod的运行逻辑差异说明
首先先修正一个常见的认知误区:classmethod本身并不会在每次生成类实例时被重新创建,它和类变量一样,仅在类定义阶段生成一次,挂载在类对象的属性字典中。你感知到的差异,本质是普通属性访问和描述符绑定逻辑的区别,具体解释如下:
1. 类变量的运行逻辑
- 类变量属于类对象的普通数据属性,在类定义代码执行完成时就完成初始化,全生命周期内仅生成一份,存储在类的
__dict__属性中 - 当类实例访问类变量时,Python会先查找实例自身的
__dict__是否有同名属性,没有的话就自动向上查找类的__dict__,直接返回类上存储的那一份变量,因此所有实例复用同一个副本,不会额外创建新对象
示例代码验证:
class TestClass: # 类定义阶段仅创建一次 shared_var = "类变量" inst1 = TestClass() inst2 = TestClass() # 两个实例访问到的是同一个对象 print(id(inst1.shared_var) == id(inst2.shared_var)) # 输出:True
2. classmethod的运行逻辑
- classmethod本身是被
@classmethod装饰器包装后的描述符对象,同样在类定义阶段创建完成,仅生成一份存储在类的__dict__中 - 你观察到的「每次实例访问得到的对象不一样」,是因为访问classmethod时会触发描述符的
__get__协议:该方法会返回一个临时的绑定方法对象,用于自动注入类对象作为cls参数,这个临时绑定对象每次访问都会生成新的,但原始的classmethod对象本身并没有被重新创建
示例代码验证:
class TestClass: @classmethod def test_cls_method(cls): pass # 直接读取类属性字典里的原始classmethod,ID固定 print(id(TestClass.__dict__["test_cls_method"])) # 多次调用输出相同ID inst1 = TestClass() inst2 = TestClass() # 从实例访问得到的是临时生成的绑定对象,ID不同 print(id(inst1.test_cls_method) == id(inst2.test_cls_method)) # 输出:False
核心差异总结
类变量是普通数据属性,访问时直接返回存储的原始对象;classmethod是描述符类型的特殊属性,访问时会触发描述符协议生成用于参数绑定的临时对象。二者的原始存储对象都仅在类定义阶段生成一次,不存在实例化时重复创建的差异。
内容的提问来源于stack exchange,提问作者Vignesh B
相关产品推荐
相关产品推荐

