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

Python多重继承中如何调用多个父类的__new__方法?

嘿,这个问题在Python多重继承玩__new__的时候太容易踩坑了!让我一步步给你理清楚问题出在哪,以及怎么解决。

问题拆解与核心原因

首先,你遇到的核心问题是Python多重继承的MRO(方法解析顺序)和__new__方法的参数传递不匹配。

当你无参数实例化C时,super(C, cls).__new__()能正常工作,是因为MRO顺序(C→A→B→object)里的每个__new__都不需要额外参数,调用链能顺畅走完:

  1. C的super调用A.__new__()
  2. A的super调用B.__new__()
  3. B的super调用object.__new__(),最终创建实例

但当你加入参数后,A只需要a,B需要foo和bar,直接把所有参数传给super会导致参数不匹配:比如A.__new__拿到a后,调用它的super(也就是B.__new__)时,没有传递foo和bar,自然会报错。

解决方案1:用关键字参数+**kwargs兼容MRO

这是最优雅的解决方案,适合你能修改A和B的代码的场景。思路是让每个父类的__new__只提取自己需要的参数,把剩余参数通过**kwargs传给MRO中的下一个类:

class A:
    def __new__(cls, a, **kwargs):
        print(f"A.__new__ 拿到参数a={a}")
        # 把剩余参数传给下一个父类
        return super().__new__(cls, **kwargs)

class B:
    def __new__(cls, foo, bar, **kwargs):
        print(f"B.__new__ 拿到参数foo={foo}, bar={bar}")
        return super().__new__(cls, **kwargs)

class C(A, B):
    def __new__(cls, a, foo, bar):
        # 用关键字参数传递,确保每个父类能拿到自己需要的参数
        return super().__new__(cls, a=a, foo=foo, bar=bar)

# 测试一下,完全没问题
c_instance = C(a=1, foo="hello", bar="world")
# 也支持位置参数(只要顺序和C的__new__一致)
c_instance2 = C(2, "hi", "there")

这种方式的好处是完全遵循Python的MRO规则,每个父类只处理自己的参数,不会干扰其他类,扩展性也强——以后加新的父类,只要也用**kwargs接收剩余参数就行。

解决方案2:手动控制父类__new__调用(无法修改父类时)

如果A和B是第三方类,你没法修改它们的__new__,那就要手动控制调用逻辑,避免MRO自动传递参数带来的冲突。

注意:__new__的核心作用是创建实例,所以只能调用一次object.__new__来创建实例,否则会重复创建对象导致问题。我们可以先创建实例,再手动调用A和B的__new__逻辑(跳过它们的super调用,因为实例已经创建好了):

class A:
    def __new__(cls, a):
        print(f"A.__new__ 处理参数a={a}")
        return super().__new__(cls)

class B:
    def __new__(cls, foo, bar):
        print(f"B.__new__ 处理参数foo={foo}, bar={bar}")
        return super().__new__(cls)

class C(A, B):
    def __new__(cls, a, foo, bar):
        # 先直接调用object.__new__创建C的实例
        instance = object.__new__(cls)
        
        # 手动调用A的__new__逻辑,但传递cls和a,并且忽略它的返回值(因为实例已经创建了)
        A.__new__(cls, a)
        # 同样手动调用B的__new__逻辑
        B.__new__(cls, foo, bar)
        
        return instance

# 测试
c_instance = C(1, "hello", "world")

这种方式要谨慎使用:如果A或B的__new__依赖于super调用的返回值,可能会有隐藏问题。但如果它们的__new__只是做参数校验、预处理之类的逻辑,这种方法是可行的。

关键总结
  • 多重继承下,super()严格按照MRO顺序调用方法,参数必须和每个步骤的方法匹配
  • 用关键字参数+**kwargs是处理多参数父类继承的最佳实践,能避免大部分参数冲突
  • 当无法修改父类时,手动控制__new__调用要确保只创建一次实例,避免重复调用object.__new__

内容的提问来源于stack exchange,提问作者Anton Ovsyannikov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 09:02:21