Python多继承中super().__new__与super().__init__执行逻辑疑问
问题1 解答
Python 多继承默认的实例化规则是:先按方法解析顺序(MRO)依次调用继承链上所有类的__new__方法,拿到最终生成的实例后,再按 MRO 顺序依次调用继承链上的__init__方法。因此在原有的son同时继承mon、far的结构下,不可能实现先跑完mon的__new__+__init__再跑far的__new__+__init__的输出,需要调整类结构,比如将far从父类改为son内部主动初始化的属性,示例代码如下:
class mon(): def __new__(cls): print("i am in mon's new") return super().__new__(cls) def __init__(self): print("i am in mon's init") super().__init__() class far(): def __new__(cls): print("i am in far's new") return super().__new__(cls) def __init__(self): print("i am in far's init") # 仅继承mon,far在初始化时主动实例化 class son(mon): def __init__(self): super().__init__() # 主动触发far的实例化流程 self.far_instance = far()
此时执行son_instance = son()的输出完全符合要求:
i am in mon's new i am in mon's init i am in far's new i am in far's init
问题2 解答
核心原因是Python的实例化触发规则:只有__new__方法返回当前待实例化类(或其子类)的实例时,才会自动执行对应的__init__方法;如果__new__返回None或者其他非目标类实例的对象,整个实例化流程直接终止,不会调用任何__init__方法。
你修改后的代码执行流程如下:
- 调用
son()时,先按MRO(son→mon→far→object)找__new__方法,首先执行mon的__new__,打印i am in mon's new mon的__new__里的super().__new__(cls)会调用下一个父类far的__new__,打印i am in far's new- 你删掉了
far的__new__的return语句,Python函数无return时默认返回None,这个None会作为整个son类__new__方法的最终返回值 - 由于返回的None不是
son类的实例,触发规则直接终止实例化流程,不会调用任何__init__方法,因此不会输出i am in mon's init
你的误解在于认为far的__new__返回值只会影响自身,实际上多继承的__new__是链式调用的,far的__new__是son实例化流程中的一环,它的返回值直接决定了整个实例化流程是否继续。
内容的提问来源于stack exchange,提问作者showkey
相关产品推荐
相关产品推荐

