8

I created the following class that represents a chest where toys (numbers) can be stored:

class Chest:

  toys = []

  def __init__(self):
    return

  def add(self, num):
    self.toys.append(num)
    return

The main code that uses this class is as follows:

room_of_chests = []

for i in range(3):

  print "Chest", i
  temp = Chest()

  print "Number of toys in the chest:", len(temp.toys)

  for j in range(5):
    temp.add(j)

  print "Number of toys in the chest:", len(temp.toys)
  print ""

  room_of_chests.append(temp)

So, for each iteration of i, I create a new Chest and make the variable temp point to it (correct?). So, in theory, in each iteration, temp would start with an empty chest and end with a chest with 5 toys (correct?).

Therefore, the output I am expecting is:

Chest 0
Number of toys in the chest: 0
Number of toys in the chest: 5

Chest 1
Number of toys in the chest: 0
Number of toys in the chest: 5

Chest 2
Number of toys in the chest: 0
Number of toys in the chest: 5

However, what I am actually getting is:

Chest 0
Number of toys in the chest: 0
Number of toys in the chest: 5

Chest 1
Number of toys in the chest: 5
Number of toys in the chest: 10

Chest 2
Number of toys in the chest: 10
Number of toys in the chest: 15

What am I doing wrong? Can someone give a quick explanation of how instantiation works in this case? And the rules of variables pointing to objects in Python? Thanks in advance.

CrazyJony
  • 925
  • 1
  • 9
  • 12

1 Answers1

11

The problem is that you have a class attribute and not an instance variable. Change your class to make it an instance variable by creating it in the __init__ function as a member of self.

Also, there's no need to use return in __init__.

class Chest:

  def __init__(self):
    self.toys = []


  def add(self, num):
    self.toys.append(num)

This is a common mistake if you're coming from a language like Java or C++.

merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • 1
    Python class attributes aren't quite the same as Java or C++ static member variables. The Python docs are very careful to avoid using the term "static variable" or "static attribute" anywhere to avoid implying anything that isn't true, and it would be better to do the same here. (Otherwise, great explanation.) – abarnert May 20 '15 at 22:48
  • Oh, also, `__init__` is the initializer; the constructor (which you rarely have to worry about) is `__new__`. – abarnert May 20 '15 at 22:50
  • Thank you for the quick reply. Do you mean to put "self.toys = [ ]" inside the __init__ function? As you wrote it, it gives an error – CrazyJony May 20 '15 at 22:50
  • @abarnert, Also a very good point. It is common to treat `__init__` as a constructor but you're correct in that it is not. – merlin2011 May 20 '15 at 22:52
  • @merlin2011 You're far quicker than me :p thanks again, it works perfectly now – CrazyJony May 20 '15 at 22:52
  • @CrazyJony, Glad to help. Please accept the answer if it resolves your question. – merlin2011 May 20 '15 at 22:52
  • @merlin2011: Yeah, even core devs sometimes call `__init__` the constructor method… but the first time I told a novice to "do it in the constructor" and he searched the docs exactly as you'd hope someone would and found a bunch of complicated stuff about `__new__` and couldn't even figure out how to ask how to use it, I learned my lesson. :) – abarnert May 20 '15 at 22:54