Python多继承中子类访问父类属性的机制解析
本文深入解析Python多继承中子类访问父类属性的现象。通过代码示例揭示,看似子类调用父类方法访问父类属性,实则是子类实例在操作。核心在于self始终指向子类实例,父类属性和方法被“转移”至子类实例中,并非存在隐藏的继承关系。
Python继承基础与属性访问现象
在面向对象编程体系中,继承是一项核心机制,允许子类复用父类的方法与属性。
参考以下代码示例:
class Father:
def __init__(self):
self.address = '上海'
def say(self):
print('我是爸爸')
class Son(Father):
def __init__(self):
super().__init__()
def say(self):
print('我是儿子')
son = Son()
print(son.address)
其运行结果如图所示:

观察可知,子类本身并未定义 self.address 属性,但在直接打印时并未报错,而是自动调用了父类的 address 属性。
反之,若子类和父类均缺失该属性,程序将抛出错误,具体表现如下:

多继承中的属性查找困惑
Python 支持 Python 多继承,即一个子类可拥有多个父类。请查看以下代码:
class GrandFather:
def __init__(self):
self.address = '上海'
def say(self):
print('我是爸爸')
class Father:
def __init__(self):
self.age = 100
def where(self):
print('我现在住在:', self.address)
class Son(GrandFather, Father):
def __init__(self):
super().__init__()
def say(self):
print('我是儿子')
son = Son()
son.where()
运行效果如图所示:

仔细观察代码逻辑,会发现一处看似异常的现象。调用 son.where() 方法时,由于 Son 类未定义该方法,解释器沿继承链查找至 Father 父类,并执行其中的 where() 方法,此过程符合预期。
然而后续步骤显得不合常理。在 where() 方法内部,代码尝试访问 self.address 属性。问题在于,Father 类并未定义该属性,且 Father 作为根类也没有父类。那么,address 属性究竟源自何处?
这是否意味着在开发者视野之外,GrandFather 类悄悄成为了 Father 的父类?若如此,GrandFather 既是 C 的父类,又是 C 的父类的父类,即 GrandFather 既是父亲又是祖父?
实际上,这种混乱的继承关系并不存在。要解释这一现象,需从 self 的本质入手。
解析self的本质与实例归属
我们知道,类的属性通常以 self 开头,方法的第一个参数也是 self 。那么 self 究竟代表什么?通过以下简短代码进行验证:
class A:
def get_self(self):
return self
test = A()
what_is_self = test.get_self()
test is what_is_self
运行结果如图所示:

从图中可见,self 实际上即为该类的实例对象。进一步考察存在继承关系的情况:
class A:
def get_self(self):
return self
class B(A):
def __init__(self):
...
test = B()
what_is_self = test.get_self()
print(what_is_self)

结果显示,尽管在 A 类的 .get_self() 方法中返回了 self ,但该 self 实际上是 B 类的实例。这是因为我们仅初始化了 B 类,从未初始化 A 类。尽管 A 是 B 的父类,但父类的 self 最终都归属于子类实例。
理解这一点后,前文的问题便迎刃而解。我们增加更多打印信息以观察细节:

请注意图中红线标注部分,self 始终指向 Son 类的实例。因此,在初始化 .address 时,实质是初始化 Son 实例的 .address 属性。后续在 .where 中调用 address 时,读取的也是 Son 实例的 address 属性。因此,并不存在 Father 类去读取 GrandFather 类属性的情况,自始至终均由 Son 类的实例执行操作。
多继承属性覆盖与映射机制总结
综上所述,在继承机制下,若子类与父类拥有同名属性或方法,子类定义优先。若子类未定义,则父类的属性和方法会直接“映射”到子类实例中。所有看似由父类执行的操作,实际上均由子类实例完成。上述代码逻辑可近似等价于以下简化理解:

由于 say 方法在子类中已定义,子类覆盖父类实现,以子类的 say 方法为准。而 where 和 address 因子类未定义,Father 类的 where 方法与 GrandFather 中的 address 属性,均直接作用于子类实例。
本文关于 Python 多继承中这一看似诡异现象的解析至此结束。如需了解更多相关内容,建议查阅本站过往文章或继续浏览后续教程,感谢大家的支持。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













