Python多重继承:如何从两个父母那里继承?

时间:2019-12-04 10:20:30

标签: python inheritance

我正在尝试理解多重继承。在我的代码中,我有两个父类,四个子类和一个孙子类,它们是从某些子类继承的。

这是我的代码:

class ParentA:
    def __init__(self, time_span):
        print('Parent A start')
        self.time_span = time_span
        self.nameA = 'Parent A'
        print('Parent A end')


class ParentB:
    def __init__(self, time_span):
        print('Parent B start')
        self.time_span = time_span
        self.nameB = 'Parent B'
        print('Parent B end')


class Child1(ParentA, ParentB):
    def __init__(self, time_span):
        print('Child1 before init')
        super().__init__(time_span)
        print('Child1 start')
        self.name_child1 = 'Child 1'
        print('Child1 end')


class Child2(ParentA, ParentB):
    def __init__(self, time_span):
        print('Child2 before init')
        super().__init__(time_span)
        print('Child2 start')
        self.name_child2 = 'Child 2'
        print('Child2 end')


class Child3(ParentA, ParentB):
    def __init__(self, time_span):
        print('Child3 before init')
        super().__init__(time_span)
        print('Child3 start')
        self.name_child3 = 'Child 3'
        print('Child3 end')


class Child4(ParentA):
    def __init__(self, time_span):
        print('Child4 before init')
        super().__init__(time_span)
        self.time = time_span
        print('Child 4, time: ', self.time)


class Grandchild(Child2, Child3, Child4):
    def __init__(self, time_span):
        print('Grandchild before init')
        super().__init__(time_span)
        self.name_grandchild = 'Grandchild'
        print('Grandchild end')


def main():
    par_a = ParentA(24)
    c1 = Child1(24)
    c2 = Child2(24)
    c3 = Child3(24)
    c4 = Child4(24)
    gc = Grandchild(24)


if __name__ == '__main__':
    main()

运行代码的输出是:

Parent A start
Parent A end
Child1 before init
Parent A start
Parent A end
Child1 start
Child1 end
Child2 before init
Parent A start
Parent A end
Child2 start
Child2 end
Child3 before init
Parent A start
Parent A end
Child3 start
Child3 end
Child4 before init
Parent A start
Parent A end
Child 4, time:  24
Grandchild before init
Child2 before init
Child3 before init
Child4 before init
Parent A start
Parent A end
Child 4, time:  24
Child3 start
Child3 end
Child2 start
Child2 end
Grandchild end

在我的设置中,没有任何孩子或孙子从ParentB继承。我想从任何子代/孙代访问nameB。我该怎么做?

我看了其他示例,例如这个:https://www.datacamp.com/community/tutorials/super-multiple-inheritance-diamond-problem(例如“多重继承,超级和钻石问题”下的示例),但是在这种情况下,顶层只有一个父级。

1 个答案:

答案 0 :(得分:0)

听起来不清楚多重继承是您所需要的,尽管尚不清楚您提供的代码是否是程序中的实际代码,或者它是否是仅用于描述代码结构的截短版本。

基于此

  

在我的设置中,没有任何孩子或孙子从ParentB继承。   我想从任何子代/孙代访问nameB。

..听起来好像您希望在整个程序中只有一个名为“ nameB”的变量,并且希望该变量可被所有其他对象访问。如果这不正确,请纠正我。 如果是这种情况,那么您可以像在“ par_a”中一样在def main()中实例化“ par_b”,或尝试为ParentB创建静态类。然后,“ B”对象的名称为“ ParentB”(而不是像在函数main()中那样实例化得到的“ par_b”命名法)。无论哪种方式,“ B”的属性都可以通过点符号来访问:

ParentB.nameB


par_b.nameB

返回到继承位-如果程序中的所有子类都继承自ParentA和ParentB,并且实例化了每个子类一次(就像在函数main()中一样):

def main():
    par_a = ParentA(24)
    c1 = Child1(24)  
    c2 = Child2(24)
    c3 = Child3(24)
    c4 = Child4(24)
    gc = Grandchild(24) 

然后您在程序中创建了5个 different 变量,称为“ nameB”,每个变量都属于不同的对象。 这意味着,如果要更改ParentB.nameB,则每个子对象仍将具有其自己的名为“ nameB”的属性,该属性将与ParentB.nameB一起更改。

此外,如果此代码是您程序的实际代码,则考虑为您要描绘的任何对象创建一个单一的类,并以相同的类类型实例化main中的所有对象,因为所有类均会出现几乎相同:

class Thing:
    def __init__(self, time_span, name):
        print(name, " start")
        self.time_span=time_span
        self.name=name
        print(self.name, " end")


par_a = Thing(24, "ParentA")
c1 = Thing(24, "Child1")
c2 = Thing(24, "Child2")
c3 = Thing(24, "Child3")
c4 = Thing(24, "Child4")
gc = Thing(24, "Grandchild")

由于默认情况下这些对象“ par_a”,“ c1”等是 public ,因此您可以从程序中的任何位置访问它们。 例如

print(par_a.name)

抱歉,如果我对您的理解不正确。希望这会有所帮助。

*正在编辑,以基于新上下文在下面的注释中添加代码示例。

#the new top level class
class Model:
    def __init__(self, geo_area):
        self.geo_area=geo_area

        #do the typical model data initialization here
        self.init_data=None
        self.avg_day_temp=self.geo_area.avg_day_temp
        self.avg_night_temp=self.geo_area.avg_night_temp
        self.module1=self.geo_area.module1        
        self.module2=self.geo_area.module2        
        self.module3=self.geo_area.module3        
        self.module4=self.geo_area.module4        
        #if there are a lot more than 4 total modules, there are definitely more organized ways of handling the initialization. Probably keep a list of the required modules in GeoAreaHawaii.

        #create a new output modifier object (what was previously the grandchild class)
        self.out_mod=OutputModifier(self.module1, self.module2, self.module3, self.module4)

    def calcOutput(self):
        print(out_mod.processData("This is a test"))


#this was the "grandchild" class, no longer part of the inheritance tree
class OutputModifier:
    def __init__(self, module1=None, module2=None, module3=None, module4=None):
        self.module1=module1
        self.module2=module2
        self.module3=module3
        self.module4=module4

    def processData(self, data):
        #process the data thru the appropriate self.module methods
        processed_data=data
        return processed_data

#this was child1
class GroundWater:
    def __init__(self):
        #init GroundWater module
        pass
    def thingsThatGroundWaterDoes():
        pass

static class GeoAreaHawaii:
    #all the details on geo_area Hawaii 


#run it
geo_model_hawaii = Model(GeoAreaHawaii)
geo_model_hawaii.calcOutput()