Python中使用super()的多重继承



我正在Python中练习多重继承。没有Boss类,一切都很顺利。非常感谢您的帮助。我提到过:Python是如何做到的';s super((处理多重继承?

反馈:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
in 
41 print(archer1.__str__())
42 print('')
---> 43 boss = Boss("Boss", 50, 50, 100)
44 print(boss.__str__())
in __init__(self, name, power, agility, HP)
27 class Boss(Worrior,Archer):
28      def __init__(self, name, power, agility, HP):
---> 29      Worrior.__init__(self, name, power, HP)
30          Archer.__init__(self, name, agility, HP)
31      def __str__(self):
in __init__(self, name, power, HP)
7 class Worrior(Player):
8     def __init__(self, name, power, HP):
----> 9     super().__init__(HP)
10         self.name = name
11         self.power = power
TypeError: __init__() missing 2 required positional arguments: 'agility' and 'HP'

它似乎是在获取Worrior类内部的power属性之后,然后停止。

class Player:
def __init__(self,HP):
self.HP = HP 
def sign_in(self):
print('player sign in')
# put the class want to extend from
class Worrior(Player):
def __init__(self, name, power, HP):
super().__init__(HP)
self.name = name
self.power = power
# it's the toString() method in java
# need to override the dunder(magic) method
def __str__(self):
return "The worrior's name: " f'{self.name} n' 
"He has the power:" f'{self.power}'
class Archer(Player):
def __init__(self, name, agility, HP):
super().__init__(HP)
self.name = name
self.agility = agility
def __str__(self):
return "The archer's name: " f'{self.name} n' 
"He has the agility:" f'{self.agility}'
class Boss(Worrior,Archer):
def __init__(self, name, power, agility, HP):
Worrior.__init__(self, name, power, HP)
Archer.__init__(self, name, agility, HP)
def __str__(self):
return "The boss's name: " f'{self.name} n' 
"With Worrior's power " f'{self.power} n' 
"and With Archer's agilit" f'{self.agility}'
"The boss' HP is: " f'{self.HP}'
boss = Boss("Boss", 50, 50, 100)
print(boss.__str__())

@Thierry Lathuille的链接是正确的,但我会尝试添加一些额外的解释。初始值设定项的MRO是[Boss,Worrior,Archer,Player]。这意味着(有点令人困惑(,当Worior调用super((时,这实际上指的是Archer,而不是Player。如果在每次调用该方法之前放置print(super().__init__),则在崩溃之前会发现这样的输出:

<bound method Worrior.__init__ of <__main__.Boss object at 0x10af5f780>>
<bound method Archer.__init__ of <__main__.Boss object at 0x10af5f780>>
Traceback (most recent call last):
...

这是Python中多重继承的主要缺陷IMHO,我通常建议不要这样做,除非你有零参数初始化器。

如果您试图显式调用每个基类初始值设定项(例如Player.__init__(,那么您最终会看到一些初始值设定值执行多次。

为了能够通过你的论点,你需要利用**kwargs。此外,当这些参数通过时,每个唯一的参数名称都将从kwargs中剥离。因此,这意味着您不能将name重新用作初始化参数。我将使用worrior_namearcher_name。因此,将所有这些放在一起,下面的程序将只运行每个初始化器一次,而不会崩溃:

class Player:
def __init__(self, hp, **kwargs):
print(super().__init__)
self.hp = hp
def sign_in(self):
print('player sign in')

class Worrior(Player):
def __init__(self, worrior_name, power, **kwargs):
super().__init__(**kwargs)
self.name = worrior_name
self.power = power
def __str__(self):
return "The worrior's name: " f'{self.name} n' 
"He has the power:" f'{self.power}'

class Archer(Player):
def __init__(self, archer_name, agility, **kwargs):
super().__init__(**kwargs)
self.name = archer_name
self.agility = agility
def __str__(self):
return "The archer's name: " f'{self.name} n' 
"He has the agility:" f'{self.agility}'

class Boss(Worrior, Archer):
def __init__(self, name, power, agility, hp):
super().__init__(archer_name=name, worrior_name=name, power=power, agility=agility, hp=hp)
def __str__(self):
return "The boss's name: " f'{self.name} n' 
"With Worrior's power " f'{self.power} n' 
"and With Archer's agilit" f'{self.agility}' 
"The boss' hp is: " f'{self.hp}'

这是因为新样式类中的方法解析顺序(MRO)。Boss类的MRO-

ipdb> Boss.mro()                                                                                                                   
[<class '__main__.Boss'>, <class '__main__.Worrior'>, <class '__main__.Archer'>, <class '__main__.Player'>, <class 'object'>]
ipdb>  

这意味着Worior类中的super((调用实际上指的是Archer,而不是Player。

你可以在新型类中引用这种堆栈溢出后方法解析顺序(MRO(?,这很好地解释了MRO如何在python中工作。

当Python到达Warrior类中的super()时,它似乎决定再次遍历整个层次结构(我已经更正了您的拼写,它不是"Worrior"(。

我不确定你哪里出了问题,也不确定这是否只是一种不能使用super()的情况。我和你一样期待,结果也让我很惊讶。

然而,下面的代码没有问题,尽管你当然会失去灵活性,我不喜欢这样做:

class Player:
def __init__(self, hp):
self.hp = hp
def sign_in(self):
print('player sign in')

class Warrior(Player):
def __init__(self, name, power, hp):
Player.__init__(self, hp)
self.name = name
self.power = power
def __str__(self):
return "The warrior's name: " f'{self.name} n' 
"He has the power:" f'{self.power}'

class Archer(Player):
def __init__(self, name, agility, hp):
Player.__init__(self, hp)
self.name = name
self.agility = agility
def __str__(self):
return "The archer's name: " f'{self.name} n' 
"He has the agility:" f'{self.agility}'

class Boss(Warrior, Archer):
def __init__(self, name, power, agility, hp):
Warrior.__init__(self, name, power, hp)
Archer.__init__(self, name, agility, hp)
def __str__(self):
return "The boss's name: " f'{self.name} n' 
"With Warrior's power: " f'{self.power} n' 
"and With Archer's agility: " f'{self.agility}'
"The boss' HP is: " f'{self.hp}'

boss = Boss("Boss", 50, 50, 100)
print(boss.__str__())

所以,并不是一个完整的答案,而是想提供反馈——希望其他人能提供一个完整答案,并解释到底发生了什么。

相关内容

  • 没有找到相关文章

最新更新