0

Suppose I had the following Player base class:

from abc import ABC, abstractmethod

class Player(ABC):

    def __init__(self, name, player_type):
        self.name = name
        self.player_type = player_type

Wizard:

from Player import Player

class Wizard(Player):

    def __init__(self, name, player_type = "Wizard"):
        super().__init__(self,name)

Main:

from Player import Player
from Wizard import Wizard


def main():

    gandalf = Wizard("Gandalf")
    print(gandalf.name)

    # Will print gandalf because the parameter assignment was shifted
    # because self was passed from the child to base class.
    print(gandalf.player_type)

if __name__ == "__main__":
    main()

I'm aware from this question, you shouldn't pass self from the subclass to the base class. That being said, suppose you made the mistake of doing so, the line print(gandalf.name) prints <Wizard.Wizard object at 0x049F20B0> because name was never assigned but what exactly does this value mean?

14
  • 1
    It means you assigned the self into name... Commented May 28, 2018 at 19:41
  • 3
    It's the string representation of the object itself: the result of repr(gandalf). Commented May 28, 2018 at 19:45
  • 2
    @AGNGazer this code would indeed work. The method expects three arguments and is being passed three arguments. The fact that two of them are self is irrelevant. Commented May 28, 2018 at 19:49
  • 1
    @Sveta it is hard to understand your question. You are passing self in the argument for name, so that is the value that is assigned; what is confusing to you? Commented May 28, 2018 at 19:50
  • 1
    Well... Going to eat my hat... You are right... I missed self! Commented May 28, 2018 at 19:50

1 Answer 1

2

super() does not return a class; it returns a proxy object, so super().__init__(self, name) behaves much the same as foo.__init__(self, name), where foo is a "real" instance of Wizard. That being the case, the first parameter self of the call to Player.__init__ has already been assigned, so your explicit self is assigned to the next parameter, name, and your second argument name is assigned to the third parameter player_type.

Put another way, with Player being the next class in the MRO, super().__init__(self, name) is the same as Player.__init__(self, self, name).

Put yet another way, super().__init__ is a bound method, and so the __init__ function's first parameter self has already been supplied.

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

4 Comments

So, I was correct in stating that it shifted the parameter assignments?
Yes, but that's normal for any bound method, just like gandalf = Wizard("Gandalf") results in an implicit call to Wizard.__init__(gandalf, "Gandalf")
In other words, don't pass self, that's done for you automatically, correct?
You can clean up the edit I made, but keep the comment about the repr(gandalf) because that's the real answer to my question, and I'll give you the checkmark.

Your Answer

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