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

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的执行流程是这样的:

  1. 先调用A.__new__(A, 1),这个方法返回了一个B类的实例
  2. 接下来Python会做一个关键判断:返回的实例的类型,是不是调用__new__的类(也就是A)或者A的子类?
    这里B和A完全没有继承关系,所以Python会认为:“你手动创建了一个无关类的实例,初始化的事情应该由你自己处理”,因此不会自动调用任何类的__init__方法,自然就没有输出了。

二、为什么让B继承A后,B的__init__会被自动调用?

当你把B改成class B(A):之后,B就成了A的子类。这时候:

  1. 同样是A.__new__返回B的实例,但此时B的实例属于A的子类类型
  2. 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._

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 10:17:58