python 多重继承使用 super 将参数传递给构造函数

2025-03-19 08:57:00
admin
原创
51
摘要:问题描述:考虑以下 Python 代码片段class A(object): def __init__(self, a): self.a = a class B(A): def __init__(self, a, b): super(B, self).__ini...

问题描述:

考虑以下 Python 代码片段

class A(object):
    def __init__(self, a):
        self.a = a

class B(A):
    def __init__(self, a, b):
        super(B, self).__init__(a)
        self.b = b

class C(A):
    def __init__(self, a, c):
        super(C, self).__init__(a)
        self.c = c

class D(B, C):
    def __init__(self, a, b, c, d):
        #super(D,self).__init__(a, b, c) ???
        self.d = d

我想知道如何将 和 传递ab相应c的基类的构造函数。


解决方案 1:

好吧,一般来说,在处理多重继承时,你的基类(不幸的是)应该为多重继承而设计。你示例中的类BC不是,因此你找不到合适的方法来super应用D

为多重继承设计基类的常见方法之一是让中级基类在其__init__方法中接受它们不打算使用的额外参数,并将它们传递给它们的super调用。

以下是使用 Python 实现此操作的一种方法:

class A(object):
    def __init__(self,a):
        self.a=a

class B(A):
    def __init__(self,b,**kw):
        self.b=b
        super(B,self).__init__(**kw)

 class C(A):
    def __init__(self,c,**kw):
        self.c=c
        super(C,self).__init__(**kw)

class D(B,C):
    def __init__(self,a,b,c,d):
        super(D,self).__init__(a=a,b=b,c=c)
        self.d=d

这看上去令人失望,但事实就是如此。

解决方案 2:

super()不幸的是,如果不更改基类,则无法实现此功能。对B或 的构造函数的任何调用C都将尝试调用方法解析顺序中的下一个类,该类始终是B或 ,C而不是和类构造函数假定的A类。B`C`

另一种方法是明确调用构造函数,而不在每个类中使用super()

class A(object):
    def __init__(self, a):
        object.__init__()
        self.a = a

class B(A):
    def __init__(self, a, b):
        A.__init__(self, a)
        self.b = b

class C(A):
    def __init__(self, a, c):
        A.__init__(self, a)
        self.c = c

class D(B, C):
    def __init__(self, a, b, c, d):
        B.__init__(self, a, b)
        C.__init__(self, a, c)
        self.d = d 

这里仍存在一个缺点,因为A构造函数将被调用两次,这在本例中实际上没有太大影响,但在更复杂的构造函数中可能会导致问题。您可以添加一个检查以防止构造函数运行多次。

class A(object):
    def __init__(self, a):
        if hasattr(self, 'a'):
            return
        # Normal constructor.

有些人会称这是 的缺点super(),从某种意义上来说确实如此,但总的来说,这也是多重继承的缺点。菱形继承模式经常容易出错。而针对它们的许多解决方法会导致更加混乱和容易出错的代码。有时,最好的答案是尝试重构代码以减少使用多重继承。

解决方案 3:

一个关键概念:super不引用父类。它引用 mro 列表中的下一个类,这取决于正在实例化的实际类。

所以在调用时super().__init__,实际调用的方法是由调用框架决定的。

这就是为什么类必须专门为 mixin 设计的原因。

即使一个类只继承自object,也应该调用super().__init__。当然,当object__init__(**kwargs) 被调用时,kwargs应该为空;否则会引发错误。

例子:

class AMix:
    def __init__(self, a, **kwargs):
        super().__init__(**kwargs)
        self.a = a

          
class BMix:
    def __init__(self, b, **kwargs):
        super().__init__(**kwargs)
        self.b = b
    
          
class AB(AMix, BMix):
    def __init__(self, a, b):
        super().__init__(a=a, b=b)
      
      
ab = AB('a1', 'b2')

print(ab.a, ab.b)  #  -> a1 b2

解决方案 4:

我对这里的答案并不完全满意,因为有时使用不同的参数为每个基类分别调用 super() 而不重构它们会非常方便。因此,我创建了一个名为 multinherit 的包,您可以使用该包轻松解决这个问题。https ://github.com/DovaX/multinherit

from multinherit.multinherit import multi_super

class A(object):
    def __init__(self, a):
        self.a = a
        print(self.a)


class B(A):
    def __init__(self, a, b):
        multi_super(A,self,a=a)
        self.b = b
        print(self.b)


class C(A):
    def __init__(self, a, c):
        multi_super(A,self,a=a)
        self.c = c
        print(self.c)


class D(B, C):
    def __init__(self, a, b, c, d):
        multi_super(B,self,a=a,b=b)
        multi_super(C,self,a=a,c=c)
        self.d = d
        print(self.d)
   

print()
print("d3")            
d3=D(1,2,3,4)
print(d3._classes_initialized)

>>> d3
>>> 1
>>> 2
>>> 3
>>> 4
>>> [<class '__main__.B'>, <class '__main__.A'>, <class '__main__.C'>]
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用