Home > OS >  Multiple Inheritance in Python - TypeError
Multiple Inheritance in Python - TypeError

Time:04-28

really struggling with this. It's been bugging for the past couple of days and I cannot get my head around it, nor find an answer that fully makes sense to me.

I'm only really getting to grips with OOP and I have been looking at multiple inheritance. The problem I have, is when I instantiate the class which inherits from more than one class, I get the following error:

TypeError: Wizard.__init__() missing 1 required positional argument: 'power'

The other classes work absolutely fine, it's just when I instantiate the 'Hybrid' class, I get the error.

Here is the code:

class User:
    def __init__(self, name):
        self.name = name

    def greet(self):
        return f"Welcome, {self.name.title()}."


class Archer(User):
    def __init__(self, name, arrows):
        super().__init__(name)
        self.arrows = arrows

    def shoot_arrow(self):
        self.arrows -= 1
        return "You shot an arrow!"

    def arrows_left(self):
        return f"You have {self.arrows} arrows remaining."


class Wizard(User):
    def __init__(self, name, power):
        super().__init__(name)
        self.power = power

    def cast_spell(self):
        return f"You cast a spell with a power of {self.power}"


class Hybrid(Archer, Wizard):
    def __init__(self, name, arrows, power):
        Archer.__init__(self, name, arrows)
        Wizard.__init__(self, name, power)

    def powerful(self):
        return "Hybrids are super powerful!"


merlin = Wizard('merlin', 1000)
robin = Archer('robin', 150)
hawk = Hybrid('hawk', 200, 650)


print(merlin.greet())
print(merlin.cast_spell())

print(robin.arrows_left())
print(robin.shoot_arrow())
print(robin.arrows_left())

Any help would be amazing and any explanations understandable for someone new to this field would be greatly appreciated.

CodePudding user response:

The classes as you have them now aren't great for use in multiple inheritance. When using multiple inheritance I prefer having constructors that agree on the same contract (use the same arguments) or no arguments at all. Here powers and arrows differ which makes calling each constructor awkward.

IMO A better way to design this class would be mixins. The mixins would have no constructors and depend on particular values being present in the classes which extend them.

Example Mixins:

class UserMixin:
    name: str

    def greet(self):
        return f"Welcome, {self.name.title()}."


class ArcherMixin(UserMixin):
    arrows: int

    def shoot_arrow(self):
        self.arrows -= 1
        return "You shot an arrow!"

    def arrows_left(self):
        return f"You have {self.arrows} arrows remaining."


class WizardMixin(UserMixin):
    power: int

    def cast_spell(self):
        return f"You cast a spell with a power of {self.power}"

Example Implementations:

class User(UserMixin):
    def __init__(self, name):
        self.name = name


class Archer(ArcherMixin):
    def __init__(self, name, arrows):
        self.name = name
        self.arrows = arrows


class Wizard(WizardMixin):
    def __init__(self, name, power):
        self.name = name
        self.power = power


class Hybrid(ArcherMixin, WizardMixin):
    def __init__(self, name, arrows, power):
        self.name = name
        self.arrows = arrows
        self.power = power

    def powerful(self):
        return "Hybrids are super powerful!"

Example usage:

merlin = Wizard('merlin', 1000)
robin = Archer('robin', 150)
hawk = Hybrid('hawk', 200, 650)

print(merlin.greet())
print(merlin.cast_spell())

print(robin.greet())
print(robin.arrows_left())
print(robin.shoot_arrow())
print(robin.arrows_left())

print(hawk.greet())
print(hawk.cast_spell())
print(hawk.arrows_left())
print(hawk.shoot_arrow())
print(hawk.arrows_left())
Welcome, Merlin.
You cast a spell with a power of 1000
Welcome, Robin.
You have 150 arrows remaining.
You shot an arrow!
You have 149 arrows remaining.
Welcome, Hawk.
You cast a spell with a power of 650
You have 200 arrows remaining.
You shot an arrow!
You have 199 arrows remaining.
  • Related