1

I am currently reading "Python Programming for the Absolute Beginning 3rd Edition". One of the challenges is:

Write a Character Creator program for a role-playing game. The player should be given a pool of 30 points to spend on four attributes: Strength, Health, Wisdom, and Dexterity. The player should be able to spend points from the pool on any attribute and should also be able to take points from an attribute and put them back into the pool.

At first I wrote it with the variables

pool = 30
strength = 0
health = 0
wisdom = 0
dexterity = 0

This section is regarding lists and dictionaries. So my question is: Is it better to use the variables in this manner or is it possible to use dictionaries? If so, is it more efficient? ie:

attributes = {
             "strength" : 0,
             "health" : 0,
             "wisdom" : 0, 
             "dexterity" : 0
             }
Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
mccdlibby
  • 183
  • 2
  • 7
  • 14
  • I would prefer the second, because then you could loop through – tckmn Jul 29 '13 at 01:46
  • 1
    For a more flexible approach: the collection of attributes seems well-suited for a class, more than a dictionary or a bunch of variables – Óscar López Jul 29 '13 at 01:48
  • I haven't gotten to classes yet in the book, however I have seen some examples of them. So if I were to do a class `def attributes:` and assign all of the values of strength, health, etc in there. I could call them later or alter them with attributes.strength, attributes.health, etc? – mccdlibby Jul 29 '13 at 01:52
  • @mccdlibby yes, and you could create other operations that _depend_ on those values. For the time being, a dictionary is more flexible, but after you study classes, you'll see that using them would be appropriate for solving this problem – Óscar López Jul 29 '13 at 01:58

5 Answers5

4

To make it short: I would go for the dictionary.

To make it long: This could be a nice example to delve directly into object oriented programming.

#! /usr/bin/python3

class Character:
        class AbilityScoreOutOfBoundsException (Exception): pass

        def __init__ (self, name):
            self.name = name
            self.stats = {k: 1 for k in ['STR', 'DEX', 'WIS', 'INT'] }

        @property
        def strength (self): return self.stats ['STR']

        @property
        def dexterity (self): return self.stats ['DEX']

        @property
        def wisdom (self): return self.stats ['WIS']

        @property
        def intelligence (self): return self.stats ['INT']

        @strength.setter
        def strength (self, amount): self.setStat ('STR', amount)

        @wisdom.setter
        def wisdom (self, amount): self.setStat ('WIS', amount)

        @dexterity.setter
        def dexterity (self, amount): self.setStat ('DEX', amount)

        @intelligence.setter
        def intelligence (self, amount): self.setStat ('INT', amount)

        def setStat (self, which, amount):
            if amount < 1: raise Character.AbilityScoreOutOfBoundsException ('Beware hero! Thou wert about to smite thyself.')
            if self.total + amount - self.stats [which] > 30: raise Character.AbilityScoreOutOfBoundsException ('Beware hero! Thou shalt not grow too mighty.')
            self.stats [which] = amount

        @property
        def total (self): return sum (self.stats.values () )

        def __repr__ (self):
            return '{}\n{}'.format (self.name, '\n'.join ('{}{:>4}'.format (which, self.stats [which] ) for which in ['STR', 'DEX', 'WIS', 'INT'] ) )

a = Character ('Daggeroth')
a.strength += 9
a.dexterity += 9
a.wisdom += 5
a.intelligence += 3
print (a)
Hyperboreus
  • 31,997
  • 9
  • 47
  • 87
2

Dictionaries in Python are implement with hash tables, so efficiency isn't an issue here. Using dictionary of attributes is better because it is more flexible.

For example, if you wanted multiple characters, then you can simply have a list of attribute dictionaries. Using variables in this case isn't maintainable (you would need something like player1Health, player2Health, ...).

jh314
  • 27,144
  • 16
  • 62
  • 82
1

In this case I would prefer valuing readability over efficiency since you probably wont be running into any performance issues with stat lookups. I'd say the dictionary looks better because

attributes['strength'] += 1

seems a lot more organized to me.

Stephan
  • 16,509
  • 7
  • 35
  • 61
1

To answer your exact question, Python stores variables in a dictionary so it doesn't make very much of a difference in terms of how the program runs whether you store them in a dictionary or simply as variables.

The built-in functions globals() and locals() return the dictionaries storing the set of variables that the respective names of those to functions suggest.

The typical way of storing these sorts of variables in a Python program would be to construct a class. I would guess that classes are covered sometime after lists and dictionaries, so this is probably getting a little bit ahead of the book.

This is what constructing a class for that would look like though:

    class Character(object):
        def __init__(self):
            self.charisma = 0
            self.dexterity = 0
            self.wisdom = 0
            self.health = 0
            self.pool = 30

This has a few advantages, but one that is really easy to see is that it allows you to create multiple characters easily.

    alice = Character()
    bob = Character()

Both alice and bob are initiated with their own copies of the variables associated with them. Python also stores class variables in dictionaries. So alice.charisma += 1 does not have any affect on bob.charisma.

alice.__dict__ would be the dictionary containing alice's copy of each of those variables.

user1612868
  • 511
  • 4
  • 10
0

I think using variables will be the more efficient method to go about this. Observe:

                    print(""""
                          1. strength \n
                          2 Health\n
                      3. wisdom\n
                      4. dexterity
                      5. remove 1 strength for point
                      6. remove 1 health for point
                      7. Remove 1 wisdom for point
                      8. remove 1 dexterity for point
                       """)

                         points=30
                         strength=0
                         health=0
                         wisdom=0
                         dexterity=0
                         default=1

                        while default:

                         choice=int(input("Select attributes that you want:"))
                            if choice==1:
                             strength+=1
                             points-=1
                             print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ")

                           elif choice==2:
                            health+=1
                            points-=1
                            print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                           elif choice==3:
                            wisdom+=1
                            points-=1
                            print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                          elif choice==4:
                           dexterity+=1
                           points-=1
                           print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                          elif oc==5:
                           strength-=1
                           points+=1
                           print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                         elif oc==6:
                          health-=1
                          points+=1
                          print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                         elif oc==7:
                          wisdowm-=1
                          points+=1
                          print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

                        elif oc==8:
                         dexterity-=1
                         points+=1
                         print("Strength:  ", strength, "\nHealth:  ", health, "\nWisdom:  ", wisdom, "\nDexterity: ", dexterity)

Of course you can also use dictionaries but the variable idea is a lot more easier, and programming is all about efficiency.