Python中的多重继承

时间:2014-04-15 19:13:20

标签: python multiple-inheritance

我开始学习Python语言,需要对我的代码进行批评以及解决我收到的错误消息。

代码创建一个带有两个祖先的Robot类;变形金刚和高达。第三类Hybrid继承自这些。我可以毫无错误地实例化Transformer和Gundam。 实例化Hybrid会返回错误。代码和错误如下:

Main.py

from multiple_inheritance import Robot, Transformer, Gundam, Hybrid

tito = Gundam("Tito", "Japan")
optimus = Transformer("Optimus Prime", "Mars")
Jaeger = Hybrid("Striker", "US")

print(tito)
print(optimus)

multiple_inheritance

class Robot(object):
    """A robot class"""
    def __init__(self, name):
            self.name = name

    def __str__(self):
            return "{name}".format(name = self.name)

class Transformer(Robot):
    """A transformer"""
    def __init__(self, name, planet):
            self.planet = planet
            super(Transformer, self).__init__(name)

    def __str__(self):
            return "Name = {name}, Planet = {planet}".\
                   format(name = self.name, planet = self.planet)

class Gundam(Robot):
    """A Gundam"""
    def __init__(self, name, country):
            self.country = country
            super(Gundam, self).__init__(name)

    def __str__(self):
            return "Name = {name}, Country = {country}".\
                   format(name = self.name, country = self.country)

class Hybrid(Transformer, Gundam):
    """Ultimate Robot"""

错误消息

Traceback (most recent call last):
  File "D:\Tech\Python\my_code\unit10\multiple_inheritance_main.py", line 5, in <module>
    Jaeger = Hybrid("Striker", "US")
  File "D:\Tech\Python\my_code\unit10\multiple_inheritance.py", line 13, in __init__
    super(Transformer, self).__init__(name)
TypeError: __init__() missing 1 required positional argument: 'country'

2 个答案:

答案 0 :(得分:4)

Hybrid的mro看起来像这样:

>>> Hybrid.__mro__
(<class '__main__.Hybrid'>, <class '__main__.Transformer'>, <class '__main__.Gundam'>, <class '__main__.Robot'>, <type 'object'>)

正如您在Transformer之后看到的那样,下一个班级是Gundam,当您从Transformer的__init__调用它时,您没有传递足够的参数:

class Transformer(Robot):
    """A transformer"""
    def __init__(self, name, planet):
            self.planet = planet
            #####This calls Gundam's __init__
            super(Transformer, self).__init__(name)

所以,重点是super()调用MRO中的下一个类而不是你预期的Transformer的基类。


super()相关的非常好的帖子:Python’s super() considered super!

答案 1 :(得分:3)

正如另一个答案中所指出的,Python为您的类构建了一个MRO(方法解析顺序),放置了Hybrid-&gt; Transformer-&gt; Gundam-&gt; Robot - 这意味着不仅会搜索丢失的方法和属性按此顺序排序的类,但这是使用&#34; super&#34;调用方法时使用的顺序。构造

我不知道有人曾说多重遗产是“容易的”#34;由于出现了复杂性,它甚至完全不属于Java语言。 然后Python可以使用&#34; super&#34;构建和MRO概念 - 但如果你 在不同超类的初始化器中需要不同的关键字,每个类必须知道如何处理它不知道的争论。

因此,混合动力将被称为&#34;名称&#34;,#34;国家&#34;和一个&#34;星球&#34;争论 - 但变形金刚不知道&#34;国家&#34;,也没有Gundams知道&#34; planet&#34;。

在Python中,您可以使用关键字参数来处理 - 您必须使您的中间类接受所有类型的关键字参数,并使用它所知道的 - 在这种情况下,它就像更改类一样简单。以这种方式__init__签名,并对super来电进行适当调整:

class Robot(object):
    """A robot class"""
    def __init__(self, name, **kwargs):
        ...

class Transformer(Robot):
    """A transformer"""
    def __init__(self, name, planet, **kwargs):
        ...      
        super(Transformer, self).__init__(name, **kwargs)

class Gundam(Robot):
    """A Gundam"""
    def __init__(self, name, country, **kwargs):
        ...      
        super(Gundam, self).__init__(name, **kwargs)
    ...

当然,在实施混合动力车时,你现在拥有 命名参数:

my_robot = Hybrid("XYZ-Star", planet="Earth", country="Japan")