You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python继承:为什么方法中的self会指向子类实例?

运行逻辑说明

你对super的作用存在常见误解,整个执行流程可以拆解为几个核心Python面向对象规则,结合代码执行步骤就能搞清楚结果为什么是2:

核心规则

  • self的指向永远和实例的实际类型一致,和方法定义在哪个类无关。只要你创建的是C类的实例,不管后续调用的__init__是定义在B类还是A类,方法接收到的self始终是这个C类实例,不会变成父类的实例。
  • Python的属性查找是动态按MRO(方法解析顺序)执行的:查找self.xxx时,会先查实例自身的属性,没有就查实例所属类的类属性,再顺着类的继承链依次往上找,不会因为当前代码写在父类里,就从父类开始找属性。
  • super不是硬引用当前类的父类,它返回的是一个绑定了当前实例的代理对象,方法查找是沿着实例对应类的MRO顺序向后遍历,不会改变self的指向。

逐行执行流程拆解

  1. 执行c = C()时,首先创建C类的实例,触发C类定义的__init__方法,此时方法内的self就是刚创建的C类实例。
  2. C的__init__中调用super().__init__(),super沿着C的MRO(C -> B -> A -> object)找到下一个实现了__init__的类是B,因此调用B类定义的__init__,注意此时方法的调用接收者还是原来的C类实例,self没有发生变化。
  3. 进入B的__init__后执行self.x取值:
    • 先查C实例自身有没有x属性:没有
    • 再查实例所属的C类,发现C类定义了类属性x = 2,直接返回2,不会继续往B类查找
  4. 取到的x=2被传给A类的__init__,赋值给实例的attr属性,因此最终c.attr的值就是2。

验证方式

如果想拿到x=1的结果,直接创建B类的实例即可:

b = B()
print(b.attr) # 输出1

此时self是B类的实例,查找self.x时会在B类找到x=1,结果就符合预期。你也可以在B的__init__中加一句print(type(self)),创建C实例时会看到输出为<class '__main__.C'>,直接验证self的指向。

内容的提问来源于stack exchange,提问作者actual_panda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 19:09:52