2

Relatively new to OOP, just messing around trying to make an NPC class for a game that should generate different instances of NPC's based on random values unless specified. Just proof-of-concept really.

However the age, gender and race attributes are duplicating for some reason even though they are generated by functions that should return random values.

I've tested the functions individually and they are doing what they're supposed to and are not complicated.

class NPC:
    def __init__(self, gender = rand_gender(), race = rand_race(),
                 age = rand(16, 70),name = "", height = 0):
        self.gender = gender
        self.race = race
        self.age = age
        if name == "":
           self.name = name_gen(self.gender)
        else: self.name = name
        if height == 0:
            self.height = height_gen(self.race)
        else: self.height = height

def rand(min, max):
    return random.randrange(min, max)

def rand_gender():
    genders = ["Male", "Female"]
    random.shuffle(genders)
    return genders[0]

def rand_race():
    races = ["Human", "Dwarf", "Elf", "Orc"]
    random.shuffle(races)
    return races[0]

npc1 = NPC()
npc2 = NPC()
npc3 = NPC()
hero = NPC("Female","Human", 26, "Hero")

print npc1
print npc2
print npc3
print hero
print npc1 == npc2

This is my class definition and the functions it is using that I'm having trouble with. The name and height functions and the__str__ method seem to be okay so I haven't included them. As you can see the gender, age and race are duplicated. Why is this happening? Can you use functions to initialize class objects?

Output:

Name: Jane Gender: Female Age:32 Race: Elf Height: 6.4
Name: Wilma Gender: Female Age:32 Race: Elf Height: 6.7
Name: Jane Gender: Female Age:32 Race: Elf Height: 6.5
Name: Hero Gender: Female Age:26 Race: Human Height: 5.7
False
DMcDonald
  • 89
  • 13
  • 1
    Default argument values are set when the function is defined, so it's using those same values on all the calls to the function that follow. – martineau Aug 03 '15 at 23:51

1 Answers1

5

This is an extremely common gotcha of python. The function definition (in this case with the named parameters) is only run once! So all the defaults are only being set once.

class NPC:
    def __init__(self, gender = rand_gender(), race = rand_race(),
                 age = rand(16, 70),name = "", height = 0): # run only once

Try doing something like

class NPC:
    def __init__(self, gender = None, ...):
         if gender is None:
            gender = rand_gender()
         # init the rest

As suggested, here is even more gotchas

Victory
  • 5,374
  • 22
  • 43
  • 2
    http://docs.python-guide.org/en/latest/writing/gotchas/ is a good explanation of the problem, might be worth linking to in addition to your explanations. – El Yobo Aug 03 '15 at 23:57
  • Ahh right! I thought that default argument values were created every time an object was created from the class, I understand now. Thank you for an elegant explanation. – DMcDonald Aug 04 '15 at 00:11