Вызвать в конструкторе класса родительский конструктор
Написал иерархию классов, а именно Weapon ->StrengthWeapon, CountableWeapon ->Bow. Как правильно вызывать в конструкторе Bow конструкторы родительских классов?
from hos_stats import Points
class Weapon:
def __init__(self, name: str, level: int, damage: int):
self._name = name
self._level = level
self._damage = damage
class StrengthWeapon(Weapon.Weapon):
def __init__(self, name: str, level: int, damage: int, strength: int):
super().__init__(name, level, damage)
self._strength = Points.Points(strength, strength)
class CountableWeapon(Weapon.Weapon):
def __init__(self, name: str, level: int, damage: int, count: int):
super().__init__(name, level, damage)
self._count = Points.Points(count, count)
class Bow(StrengthWeapon.StrengthWeapon, CountableWeapon.CountableWeapon):
LEVEL_DAMAGE = (5,)
LEVEL_STRENGTH = (35,)
LEVEL_COUNT = (12,)
def __init__(self, name: str, level: int):
damage = self.LEVEL_DAMAGE[level - 1]
strength = Points.Points(self.LEVEL_STRENGTH[level - 1], self.LEVEL_STRENGTH[level - 1])
count = Points.Points(self.LEVEL_COUNT[level - 1], self.LEVEL_COUNT[level - 1])
super().__init__(name, level, damage, strength)
super(CountableWeapon.CountableWeapon).__init__(self, name, level, damage, count)
bow = Bow('My bow', 1)
# Traceback (most recent call last):
# File "d:\Python\Heart of Sword\main.py", line 32, in <module>
# Bow.Bow('Emerald Bow', 1)
# File "d:\Python\Heart of Sword\hos_weapons\Bow.py", line 18, in __init__
# super().__init__(name, level, damage, strength)
# File "d:\Python\Heart of Sword\hos_weapons\StrengthWeapon.py", line 9, in __init__
# super().__init__(name, level, damage)
# TypeError: CountableWeapon.__init__() missing 1 required positional argument: 'count'
Ответы (1 шт):
Автор решения: Amgarak
→ Ссылка
Могу предложить 2 варианта:
1) Через super()
class Weapon():
def __init__(self, name, level, damage, **kwargs):
# super().__init__(**kwargs)
print("Weapon", ": ", name, ": ", level, ": ", damage)
class StrengthWeapon(Weapon):
def __init__(self, name: str, level: int, damage: int, strength: int, **kwargs):
super().__init__(name, level, damage, **kwargs)
print("StrengthWeapon", ": ", name, ": ", level, ": ", damage, ": ", strength)
class CountableWeapon(Weapon):
def __init__(self, name: str, level: int, damage: int, count: int, **kwargs):
super().__init__(name, level, damage, **kwargs)
print("CountableWeapon", ": ", name, ": ", level, ": ", damage, ": ", count)
class Bow(StrengthWeapon, CountableWeapon):
def __init__(self, name, level):
kwargs = {
"damage" : 100,
"count" : (16, 24),
"strength" : (12, 6),
}
super().__init__( name, level, **kwargs)
# super().__init__(name, level, damage=100, count=(16, 24), strength=(12, 6))
print("Bow", ": ", name, ": ", level)
Bow('My bow', 1)
Вывод:
Weapon : My bow : 1 : 100
CountableWeapon : My bow : 1 : 100 : (16, 24)
StrengthWeapon : My bow : 1 : 100 : (12, 6)
Bow : My bow : 1
2) Явно указывать классы
class Weapon():
def __init__(self, name, level, damage):
print("Weapon", ": ", name, ": ", level, ": ", damage)
class StrengthWeapon(Weapon):
def __init__(self, name, level, damage, strength):
print("StrengthWeapon", ": ", name, ": ", level, ": ", damage, ": ", strength)
Weapon.__init__(self, name, level, damage)
class CountableWeapon(Weapon):
def __init__(self, name, level, damage, count):
print("StrengthWeapon", ": ", name, ": ", level, ": ", damage, ": ", count)
Weapon.__init__(self, name, level, damage)
class Bow(StrengthWeapon, CountableWeapon):
def __init__(self, name, level):
print("Bow", ": ", name, ": ", level)
damage = 100
count= (16, 24)
strength = (12, 6)
StrengthWeapon.__init__(self, name, level, damage, strength)
CountableWeapon.__init__(self, name, level, damage, count)
Bow('My bow', 1)
Вывод:
Bow : My bow : 1
StrengthWeapon : My bow : 1 : 100 : (12, 6)
Weapon : My bow : 1 : 100
StrengthWeapon : My bow : 1 : 100 : (16, 24)
Weapon : My bow : 1 : 100
Оба варианта работают, но если делать через super()
то он позаботится о том, что бы не вызывать Weapon
дважды. Так же если что-то в коде поменяется, то не нужно будет править явные вызовы.