我正在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_name
和archer_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__())
所以,并不是一个完整的答案,而是想提供反馈——希望其他人能提供一个完整答案,并解释到底发生了什么。