0

I'm a student currently learning Python and was wondering how the question in the title could be solved. For a project, I'm creating a game that uses a class to store certain variables for different characters. Below is a portion of the class:

class character(object):
    def __init__(self, vitality):
            self.vitality = vitality
            self.stats = f'Vitality: {self.vitality}'

I haven't included the full class as I have like 41 variables in it, some of which are based on a combination of the others, but this is the gist of it.

Later in the code, I let the user choose a variable to increment by 1 in order to level up:

levelUpChoice = ''
levelUpChoiceList = ['1', '2', '3', '4', '5', '6', '7']

while levelUpChoice == '':
    levelUpChoice = input('What stat would you like to increase?\n1) Vitality\n2) Endurance\n3) Strength\n4) Dexterity\n5) Wisdom\n6) Faith\n7) Luck\n\n  > ')

    if levelUpChoice not in levelUpChoiceList:
        levelUpChoice = ''
        print('That is not an accepted response!\nUse a number 1-7.')

if int(levelUpChoice) == 1:
    charClass.vitality += 1

However, the class variable called "stats" doesn't get updated when I increment "vitality" by 1, even though it's based on it. As I literally learned about classes and how to generally use them 2 days ago, I'm not quite sure how to deal with this, but I need a solution for the project to have full functionality. Seeing as my most important class variables depend on the basic ones I plan on changing, I really need a solution.

Any tips or suggestions would be greatly appreciated.

  • The variable is not "based on it". It simply copied the value at the time you did the assignment. There's no permanent link between the variables. – Barmar Dec 08 '21 at 19:38
  • 2
    You don't need the `stats` variable. Write a method that generates the stats string when you need it. – Barmar Dec 08 '21 at 19:40
  • @Barmar ohhh I should have thought of that, it was an assignment, therefore they would obviously not be linked in any way. That makes sense. – AustinH1242 Dec 09 '21 at 00:42

3 Answers3

0

Make stats a property. That will cause it to be re-computed every time you access it. A property is essentially syntactic sugar around a method that makes it act like any other type of attribute -- i.e. you can treat self.stats as a regular string even though it's actually a function call.

class Character:
    def __init__(self, vitality: int):
        self.vitality = vitality

    @property
    def stats(self) -> str:
        return f'Vitality: {self.vitality}'

(Note that explicitly inheriting from object isn't necessary, and standard Python style is to capitalize class names.)

Samwise
  • 68,105
  • 3
  • 30
  • 44
  • So when I call it, it would be formatted as "stats(charClass)" if charClass is the name of the instance, right? – AustinH1242 Dec 08 '21 at 19:47
  • You'd refer to it as `charClass.stats`, exactly as in your original code -- that's the magic of `@property`! Without the `@property` decorator you'd have to call the method explicitly, i.e. `charClass.stats()`. If you wanted your code to be as verbose/confusing as possible, you *could* do `Character.stats(charClass)`, but don't do that. Just think of it as "the `stats` of `charClass`", which in python is written `charClass.stats`. – Samwise Dec 08 '21 at 19:49
  • Thank you! That totally worked and I appreciate the tip for capitalizing class names as well! – AustinH1242 Dec 09 '21 at 00:36
0

Some ways to fix that:

update the vitality by a setter and also change the stats:

class character(object):
    def __init__(self, vitality):
            self.vitality = vitality
            self.stats = f'Vitality: {self.vitality}'

    def set_vitality(self, val):
        self.vitality = val
        self.stats = f'Vitality: {val}'

Or a more advanced concept use @property

class character(object):
    def __init__(self, vitality):
            self.vitality = vitality

    @property
    def stats(self):
        return f'Vitality: {self.vitality}'
Pedro Maia
  • 2,666
  • 1
  • 5
  • 20
  • Thanks! I'm now using the @property method but it's good to know that I can use a function like set_vitality as well if I needed to. – AustinH1242 Dec 09 '21 at 00:38
0

If all you need is to update the stats attribute, the easiest option is probably to make it a property.

class character(object):
    def __init__(self, vitality):
            self.vitality = vitality

    #Accessed when character.stats is called
    #and constructs string at call time
    @property
    def stats(self):
        return f'Vitality: {self.vitality}'

There's quite a detailed discussion of properties here: How does the @property decorator work in Python?

defladamouse
  • 567
  • 2
  • 13