Search code examples
pythonpython-3.xsuper

super() can't increment the class variable of parent class but it updates parent class' class dictionary


I am encountering a weird problem on this following code snippet:

class Magical_SportsPerson:
    database = {}
    playerNo = 0
    def __init__(self,name,team,jerseyNo):
        self.name = name
        self.team = team
        self.jerseyNo = jerseyNo
    
    def __str__(self):
        return "Name:{}\nTeam:{}\nJerseyNo:{}".format(self.name,self.team, self.jerseyNo)
    
class Quidditch_Player(Magical_SportsPerson):
    def __init__(self,name,team,jerseyNo,goals = None,retirement_date = "Not yet retired"):
        super().__init__(name,team,jerseyNo)
        super().playerNo += 1 # for some weird reason, super().playerNo is not working
        self.goals = goals
        self.retirement_date = retirement_date

        # create a player ID in the format of "playerNo + first letter of first name + first letter of last name + jersey number"
        self.playerID = str(super().playerNo) + self.name[0] + self.name[self.name.index(" ") + 1] + str(self.jerseyNo)

        # create a list of player details in the format of [name, team, jerseyNo, goals, retirement_date]
        self.playerDetails = [self.name, self.team, self.jerseyNo, self.goals, self.retirement_date]
        
        # add the player to the database
        super().database[self.playerID] = self.playerDetails

    def __str__(self):
        details = Magical_SportsPerson.__str__(self) + "\nGoals:{}".format(self.goals) + "\nRetirement Date:{}".format(self.retirement_date)
        return details
    
    @classmethod
    def createPlayer(cls,name,team,jerseyNo,goals = None ,retirement_date = "Not yet retired"):
        return cls(name,team,jerseyNo,goals,retirement_date)

Now, if run this code with any object like:

p1 = Quidditch_Player("Harry Potter","Gryffindor", 8, 523)
print("------Details of the player------")
print(p1)

I am getting the following error: AttributeError: 'super' object has no attribute 'playerNo'

but if I do Magical_SportsPerson.playerNo += 1 it works fine.

My question is if database and playerNo both are class variables in parent class (here Magical_SportsPerson), then why super().playerNo += 1 does NOT work but super().database[self.playerID] = self.playerDetails works properly?

super().playerNo += 1 does not work, but Magical_SportsPerson.playerNo += 1 works fine.


Solution

  • The reason super().playerNo += 1 doesn't work is because super() returns a special object that just delegates getting attributes to the superclass and that special object doesn't allow setting attributes.
    (link to the documentation for super(): https://docs.python.org/3.9/library/functions.html#super).

    The reason super().database[self.playerID] = self.playerDetails does work is because you're getting the .database attribute on the superclass and setting one of its items. Notice that you're never actually setting the attribute on the superclass here (only modifying the attributes in place)