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

Python多继承未调用父类构造是否合规?如何用super处理带参构造?

多继承中未调用父类构造函数的疑问及super()的使用困惑

问题背景

我成功通过多继承构造了一个Python对象,但感觉所用方式并不规范。

我的代码

class A:
    def __init__(self, a):
        print("A ctor called!")
        self.a_ = a

    def printa(self):
        print(self.a_)


class B:
    def __init__(self, b):
        print("B ctor called!")
        self.b_ = b
    
    def printb(self):
        print(self.b_)


class C(A, B):
    def __init__(self, a, b, c):
        self.a_ = a
        self.b_ = b
        self.c_ = c

执行代码及输出

执行:

c = C(11, 22, 33)
c.printb()

输出:

22

疑问点

  • 构造C类对象时并未调用A类和B类的构造函数,但结果符合预期,这种情况是否正常?是不是操作有误?
  • 知道应该使用super()函数,但不知道如何在多继承场景下用它调用两个带参数的父类构造函数。
  • 我的问题被标记为重复,但我认为并非完全重复:相关话题未涉及带参数的构造函数问题,而我的问题核心正是参数带来的困扰。

1. 未调用父类构造函数却能运行的原因

这种情况是正常的,但属于不规范的写法。

Python中,子类如果重写了__init__方法,默认不会自动调用父类的__init__。你的代码里,C类自己手动设置了self.a_和self.b_,刚好和A、B类构造函数要初始化的属性同名,所以调用printa()、printb()时能正常访问到属性。

但这种写法有严重隐患:

  • 如果父类构造函数里还有其他逻辑(比如打印日志、初始化其他隐藏属性、连接资源等),这些逻辑完全不会执行,可能导致父类功能异常。
  • 如果后续父类修改了属性名或构造逻辑,子类代码会直接失效,维护性极差。

2. 多继承下用super()调用带参数的父类构造函数

要正确处理多继承的构造函数调用,关键是让所有父类的__init__都遵循协作式调用的规范——每个父类的__init__都要调用super().__init__(),并接受额外的关键字参数(避免参数冲突)。

调整后的代码示例:

class A:
    def __init__(self, a, **kwargs):
        print("A ctor called!")
        self.a_ = a
        super().__init__(**kwargs)  # 传递剩余参数给下一个父类

class B:
    def __init__(self, b, **kwargs):
        print("B ctor called!")
        self.b_ = b
        super().__init__(**kwargs)  # 即使B没有后续父类,这行也无害(会调用object的__init__)

class C(A, B):
    def __init__(self, a, b, c):
        super().__init__(a=a, b=b)  # 通过关键字参数传递父类需要的参数
        self.c_ = c

执行c = C(11,22,33)时,输出会是:

A ctor called!
B ctor called!

此时调用c.printa()和printb()也能正常输出,同时父类的构造逻辑都被执行了。

为什么要这么写?

  • Python的多继承是基于**方法解析顺序(MRO)**的,super()会自动按照MRO顺序调用下一个类的方法。C的MRO是[C, A, B, object],所以super().__init__()在A中会调用B的__init__,在B中会调用object的__init__。
  • 使用关键字参数传递,可以避免不同父类的参数顺序冲突,让代码更健壮。
  • 这种写法符合Python的设计规范,即使后续添加或调整父类,代码也能保持兼容。

3. 关于"重复问题"的补充

你提到的话题虽然基础,但带参数的多继承构造确实是容易混淆的点。核心差异就在于必须让父类通过**kwargs接受并传递剩余参数,否则会出现参数不匹配的错误。只要掌握了协作式调用的规范,带参数的多继承构造就能正确实现。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 12:45:28