Python中__new__方法的异常行为及初始化逻辑疑问
Python中__new__方法的异常行为及初始化逻辑疑问
嘿,这个问题问得特别到位,刚好触及了Python里__new__和__init__协作的核心规则,我一步步给你拆解清楚~
一、为什么第一种无继承关系的场景下,没有任何__init__被调用?
先看你最初的代码:
class A: def __new__(cls, *args, **kwargs): return super().__new__(B) def __init__(self, param): print(param) class B: def __init__(self, param): print(param) if __name__ == '__main__': a = A(1)
当你调用A(1)时,Python的执行流程是这样的:
- 先调用
A.__new__(A, 1),这个方法返回了一个B类的实例 - 接下来Python会做一个关键判断:返回的实例的类型,是不是调用
__new__的类(也就是A)或者A的子类?
这里B和A完全没有继承关系,所以Python会认为:“你手动创建了一个无关类的实例,初始化的事情应该由你自己处理”,因此不会自动调用任何类的__init__方法,自然就没有输出了。
二、为什么让B继承A后,B的__init__会被自动调用?
当你把B改成class B(A):之后,B就成了A的子类。这时候:
- 同样是
A.__new__返回B的实例,但此时B的实例属于A的子类类型 - Python判断到返回的实例是调用
__new__的类(A)的子类实例,就会自动触发该实例所属类的__init__方法,也就是B.__init__(实例, 1),所以你会看到输出1。
简单来说,Python自动调用__init__的规则是:只有当__new__返回的实例是当前调用类(或其子类)的实例时,才会自动调用该实例对应的__init__,并且把你调用类时传入的参数传递进去。
三、为什么手动调用obj.__init__能实现预期效果?
在第一种无继承的场景里,既然Python不会帮你自动触发初始化,那你就需要自己显式调用返回实例的__init__方法,把参数传递进去,完成初始化工作。
你修改后的代码:
class A: def __new__(cls, *args, **kwargs): obj = super().__new__(B) obj.__init__(*args, **kwargs) # 手动触发B的初始化 return obj
这里你主动调用了B实例的__init__,相当于替Python完成了它原本不会做的初始化步骤,所以就能看到B的__init__输出内容了。
核心总结
__new__的返回值类型是决定后续是否自动调用__init__的关键- 自动调用
__init__的前提:返回的实例是调用__new__的类(或其子类)的实例 - 如果返回的是完全无关类的实例,必须手动调用该实例的
__init__来完成初始化
备注:内容来源于stack exchange,提问作者demetere._
相关产品推荐
相关产品推荐

