Super simple yet essential problem

Hello,

I’m fairly new to python, and I’m having an issue regarding scope (at least I think that is what the issue is. In this code, I’m trying to update it so that the level changes, and so do all of the stats (self.str, self.att, self.def) but when I run the code the level goes up but the relevant stats do not change. I’m feeling like there’s an essential piece of logic I’m missing about how python works in terms of scope. Could somebody explain to me what’s going on here?

class Player ():
    def __init__(self):
        self.level = 1.0
        self.str = self.level * 1.5
        self.att = self.str * 1.1
        self.defense = self.str * 2.1

    def levelup(self):
        self.level += 1

    def displayLvl(self):
        print('Level: ' + str(self.level) + ', Strength: ' + str(self.str) + ', Attack: ' + str(self.att) + ', Defense: ' + str(self.defense))


player1 = Player()

player1.displayLvl()
player1.levelup()
player1.displayLvl()

Your stats are set statically at initialization, they don’t change dynamically when self.level changes. One option is to have an update method:

class Player:
    def __init__(self):
        self.level = 1.0
        self._update_stats()

    def _update_stats(self):
        self.str = self.level * 1.5
        self.att = self.str * 1.1
        self.defense = self.str * 2.1

    def levelup(self):
        self.level += 1
        self._update_stats()

    def displayLvl(self):
        print('Level: ' + str(self.level) + ', Strength: ' + str(self.str) + ', Attack: ' + str(self.att) + ', Defense: ' + str(self.defense))


player1 = Player()

player1.displayLvl()
player1.levelup()
player1.displayLvl()

Another approach would be to calculate these every time they’re requested, using property:

class Player:
    def __init__(self):
        self.level = 1.0

    @property
    def str(self):
        return self.level * 1.5

    @property
    def att(self):
        return self.str * 1.1

    @property
    def defense(self):
        return self.str * 2.1

    def levelup(self):
        self.level += 1

    def displayLvl(self):
        print('Level: ' + str(self.level) + ', Strength: ' + str(self.str) + ', Attack: ' + str(self.att) + ', Defense: ' + str(self.defense))


player1 = Player()

player1.displayLvl()
player1.levelup()
player1.displayLvl()

Edit: Fixed mistake pointed out by @franklinvp.

1 Like

It looks like you wanted to also call self._update_stats() inside your

1 Like

I did, and then I forgot. Good catch.

Thank you much! I like the conciseness of the property decorator which I didnt know about until now. That helps. But for learnings sake, I did follow the other one as well and that helps! Thanks to @effigies and @franklinvp for the help!