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

Python多继承类初始化问题:如何正确初始化依赖另一基类属性的Foobar子类

Python多继承类初始化问题:如何正确初始化依赖另一基类属性的Foobar子类

首先,咱们先拆解下你代码报错的核心原因:当你在Foobar的__init__里写super().__init__(self.foo)时,self.foo根本还没被创建出来!因为此时Foo类的初始化逻辑还没执行,self对象还没经过Foo的初始化流程,自然没有foo这个属性。而且这里的super()调用也不符合你的需求——Python多继承里的super()是按MRO(方法解析顺序)来调用下一个类的方法,Foobar的MRO是Foobar → Foo → Bar → object,所以super().__init__会先调用Foo的__init__,但Foo的__init__不需要参数,你传了self.foo本身就会引发参数不匹配的错误,更别说这个属性还不存在了。

那正确的初始化方式应该是先显式完成Foo的初始化,拿到需要的属性后,再显式初始化Bar,直接调用两个基类的__init__方法并传入self:

class Foo:
    def __init__(self):
        self.foo = 'foo'
        
class Bar:
    def __init__(self, attr):
        self.attr = attr

    def bar(self):
        print(self.attr + 'bar')
        
class Foobar(Foo, Bar):
    def __init__(self):
        # 先初始化Foo,给self添加foo属性
        Foo.__init__(self)
        # 再用已存在的self.foo初始化Bar
        Bar.__init__(self, self.foo)

测试一下这个代码:

>>> fb = Foobar()
>>> fb.bar()
foobar

完全可以正常运行,不会再出现属性错误。

结合你的实际使用场景聊聊

你提到Bar实际是FigureCanvasQTAgg,Foobar对应MplCanvas,想把Matplotlib的逻辑抽到Foo类里,方便做非PySide的前端。这个思路没问题,调整后的初始化逻辑也完全适用:

  1. 让Foo负责创建Matplotlib的Figure对象(对应示例里的self.foo);
  2. Foobar先初始化Foo拿到figure,再把figure传给FigureCanvasQTAgg的__init__(因为FigureCanvasQTAgg的构造确实需要一个Figure实例)。

关于你后来想到的替代方案

你说把foo的创建放到单独函数里,再实例化Foo或Foobar,这个思路也非常合理!这样可以彻底避开多继承初始化的依赖问题,代码逻辑会更直观,比如:

def create_figure():
    # 实际这里是创建Matplotlib Figure的逻辑
    return 'foo'

# 单独使用Foo
fig = create_figure()
foo_obj = Foo()
foo_obj.foo = fig

# 使用Foobar
fig = create_figure()
fb_obj = Foobar()
fb_obj.foo = fig
# 也可以把create_figure()直接写到Foobar的__init__里

这种方式对新手更友好,也减少了多继承带来的复杂度,如果你觉得这样更省心,完全可以采用这个方案。

备注:内容来源于stack exchange,提问作者Ilya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:20:30