Вызвать в конструкторе класса родительский конструктор

Написал иерархию классов, а именно 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 дважды. Так же если что-то в коде поменяется, то не нужно будет править явные вызовы.

→ Ссылка