Python子类C实例c.x为何输出dog而非lemon,及实例指向全局帧问题求助
x = "dog" class A: x = "cat" class B(A): x = "ferret" def __init__(self): self.x = x class C(B): x = "lemon" c = C() a = A() print(f"{c.x = }") # 输出 "dog" print(f"{a.x = }") # 输出 "cat"
为什么c.x输出为dog而非lemon
C类没有自定义__init__方法,实例化C()时会自动调用父类B的__init__方法。
核心逻辑在B的__init__赋值语句self.x = x:等号右侧的x没有加self.或者类前缀,Python解析变量会按照「方法本地作用域→外层作用域」的顺序查找:
__init__方法内部没有定义本地变量x- Python的类块不会为内部的方法创建嵌套作用域,方法的外层作用域直接是模块全局作用域,因此这里的x会直接取全局定义的
x = "dog"
赋值完成后,C类实例就有了实例属性x,值为dog。而Python访问属性的优先级是:实例属性 > 所属类的类属性 > 父类的类属性,所以c.x会直接返回实例上的dog,不会查找C类定义的类属性lemon。
虚线框内的self代表什么
self就是你实例化得到的C类实例对象,也就是代码里变量c指向的那个对象。
为什么self的父帧是全局帧
这里的父帧指的是B的__init__方法执行时的外层作用域:Python中类内部定义的方法,其外层作用域是方法定义所在的模块全局作用域,而非类的作用域。所以__init__里查找变量x时最终会落到全局帧,给self赋值的x属性值就来自全局帧的dog。
内容的提问来源于stack exchange,提问作者somniumm
相关产品推荐
相关产品推荐

