Home > OS >  Multiple Inheritance Python __init__ not working
Multiple Inheritance Python __init__ not working

Time:03-09

I have these 2 classes:

from avatar import Avatar    
class Caster(Avatar):
    def __init__(self, name, life, strength, protection, mana):
        super().__init__(name, life, strength, protection)
        self._mana = mana

and:

from avatar import Avatar
class Melee(Avatar):
    def __init__(self, name, life, strength, protection, shield):
        super().__init__(name, life, strength, protection)
        self._shield = shield

Both of them inherit from:

class Avatar:
    def __init__(self, name, life, strength, protection):
        self._name = name
        self._life = life
        self._strength = strength
        self._protection = protection

Now I want to create a new class which inherits from both Caster and Melee

from melee import Melee
from caster import Caster
class Chaman(Melee, Caster):         
    def __init__(self, name, life, strength, protection, shield, mana):    
        Melee().__init__(self, name, life, strength, protection, shield)
        Caster().__init__(self, mana)

This new class combines elements from Melee and Caster. When I execute this and try to create new Chaman objects, it gives me this error:

TypeError: __init__() missing 5 required positional arguments: 'name', 'life', 'strength', 'protection', and 'shield'

CodePudding user response:

Design your classes and use super correctly, as discussed in further detail at Python's super() considered super!.

class Avatar:
    def __init__(self, *, name, life, strength, protection, **kwargs):
        super().__init__(**kwargs)
        self._name = name
        self._life = life
        self._strength = strength
        self._protection = protection


class Caster(Avatar):
    def __init__(self, *, mana, **kwargs):
        super().__init__(**kwargs)
        self._mana = mana


class Melee(Avatar):
    def __init__(self, *, shield, **kwargs):
        super().__init__(**kwargs)
        self._shield = shield


class Chaman(Melee, Caster):
    pass


# Note that the order of the *keyword* arguments does not matter.
c = Chaman(name="bob", life=3, strength=10, protection=5, mana=9, shield=0)

Each class only deals with the arguments it introduces, passing any others up the stack via super.

Since Chaman.__init__ isn't defined, Melee.__init__ will be called first; it will call Caster.__init__ (not Avatar.__init__), which will call Avatar.__init__, which will call object.__init__, which will do nothing.

  • Related