0

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'
3
  • 3
    You defined Caster.__init__ to take all these arguments, but when you call Caster().__init__ in Chaman.__init__ you don't provide them. Also Caster() already implicitly calls Caster.__init__ (with no arguments at all), so you meant Caster.__init__(...). Commented Mar 2, 2022 at 10:54
  • Don't mix super with explicit base class references. Chaman.__init__ should just call super().__init__(name, life, strength, protection, shield) and let the base classes figure things out. You might have to swap the base classes, though. Commented Mar 2, 2022 at 10:57
  • @MisterMiyagi I have deleted this lines from Chaman.__init__: Melee().__init__(self, name, life, strength, protection, shield) Caster().__init__(self, mana) Now the error it gives is: __init__() takes 6 positional arguments but 7 were given Which changes do you mean that I have to do? Commented Mar 2, 2022 at 12:16

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you and sorry for my incompetence, I am new at this. I have written the code as you say and now it looks like yours; the class Chaman now does not have 'init 'defined by me, I understand it inherits it from the other two classes. The problem is that it gives me the error "__init__() got an unexpected keyword argument 'mana'" when I try to create new objects. As long as I understand this is because in "melee" there is no atribute "mana" while in "caster" there is, but for some reason, Python is not checking atributes of Caster. Thank you again.
The code above does not produce that error. You may have forgotten to add **kwargs to the signature of Melee.__init__ or Avatar.__init__.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.