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

解决多混入类中__init_subclass__参数名冲突的问题

解决多混入类中__init_subclass__参数名冲突的问题

这个问题的核心在于你直接调用B.__init_subclass__.__func__(cls, ...)时,破坏了Python的方法解析顺序(MRO)逻辑。B并不是AB的直接父类,所以当B的__init_subclass__里调用super().__init_subclass__()时,Python找不到正确的父类链,才会抛出那个类型错误。

我给你一个简单的修复方案,核心是让适配器类B_真正继承B,这样MRO就能正常工作,同时重写__init_subclass__来完成参数名的映射:

class A:
    def __init_subclass__(cls, msg, **kwargs):
        print(f'{cls=} A: {msg}')
        super().__init_subclass__(**kwargs)

class B:
    def __init_subclass__(cls, msg, **kwargs):
        print(f'{cls=} B: {msg}')
        super().__init_subclass__(**kwargs)

# 让B_继承B,这样AB的MRO会包含B,super调用链正常
class B_(B):
    # 重写__init_subclass__,接收msg_b并映射为msg传给父类B
    def __init_subclass__(cls, msg_b, **kwargs):
        super().__init_subclass__(msg=msg_b, **kwargs)

class AB(A, B_, msg='Hello.', msg_b='Also, hello.' ):
    pass

print(f'{AB()=}, {isinstance(AB(), A)=}, {isinstance(AB(), B_)=}, {isinstance(AB(), B)=}')

运行这段代码后,你会看到预期的输出,而且不会再报错:

cls=<class '__main__.AB'> A: Hello.
cls=<class '__main__.AB'> B: Also, hello.
AB()=<__main__.AB object at 0x102345678>, isinstance(AB(), A)=True, isinstance(AB(), B_)=True, isinstance(AB(), B)=True

为什么这个方案有效?

  • MRO正确性:B_继承B后,AB的MRO变成了AB → A → B_ → B → object,当A的__init_subclass__调用super()时,会找到B_的方法,B_的super()又会找到B的方法,整个调用链完全符合Python的继承逻辑。
  • 参数映射自然:B_的__init_subclass__接收msg_b参数,再把它作为msg传给父类B的方法,完美解决了参数名冲突的问题。
  • 无需手动转发属性:因为B_继承了B,AB的实例自动拥有B的所有属性和方法,你原来写的__init__和__getattr__转发逻辑完全可以删掉,代码更简洁。

如果你因为某些原因不想让B_继承B,还有一个替代方案:在调用B的__init_subclass__时,手动跳过它的super()调用(但这会破坏B原有的继承逻辑,不推荐),代码大概是这样:

class B_:
    def __init_subclass__(cls, msg_b, **kwargs):
        # 直接实现B的__init_subclass__逻辑,但不触发它的super调用
        print(f'{cls=} B: {msg_b}')
        # 注意:这里跳过了B的super().__init_subclass__(),如果B依赖这个调用会出问题
        super().__init_subclass__(**kwargs)

    def __init__(self, *args, **kwargs):
        self.b = B(*args, **kwargs)

    def __getattr__(self, item):
        return getattr(self.b, item)

但这个方案有明显缺陷,比如如果B的__init_subclass__里的super()调用是必要的(比如它还继承了其他类),那么这个方法就会导致逻辑缺失。所以优先推荐第一种继承式的适配器方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 20:03:12