Python中的多重继承

2 投票
2 回答
632 浏览
提问于 2025-04-18 02:51

我刚开始学习Python语言,需要对我的代码进行点评,并解决我遇到的错误信息。

这段代码创建了一个名为Robot的类,它有两个父类:Transformer和Gundam。还有一个第三个类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 个回答

4

Hybrid的类继承顺序看起来像这样:

>>> 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()调用的是继承顺序中的下一个类,而不是你预期的Transformer的基类。


这里有一篇很好的文章,和super()有关:Python的super()被认为是超级的!

3

正如其他回答中提到的,Python 为你的类构建了一个方法解析顺序(MRO),这个顺序是 Hybrid -> Transformer -> Gundam -> Robot。这意味着,当你调用方法时,Python 会按照这个顺序去查找缺失的方法和属性。同时,这个顺序也会在使用 "super" 关键字时被遵循。

我不知道有没有人说过多重继承是“简单”的。由于多重继承带来的复杂性,Java 语言甚至完全不支持它。Python 通过 "super" 关键字和 MRO 概念让多重继承变得可用,但如果你在不同的父类的初始化方法中需要不同的关键字参数,每个类都必须知道如何处理它不认识的参数。

比如,Hybrid 类在调用时需要传入 "name"、"country" 和 "planet" 这三个参数,但 Transformer 类并不知道 "country" 是什么,Gundam 类也不知道 "planet" 是什么。

在 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)
    ...

当然,当你实例化一个 Hybrid 时,你现在需要给参数命名:

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

撰写回答