1

I have a simple class with a string and a dictionary. When I make multiple objects of the class, apparently the dictionary does not get initialized properly. Dictionaries of all objects contains the entry for last object created. The code is:

# a simple class with a string and a dictionary:
class Myclass:
    name = ""
    valuedict = {}

# a list for objects: 
mylist = []

# create 3 objects: 
for i in range(3):
    mc = Myclass()
    mc.name = str(i)
    mc.valuedict['name'] = str(i)
    mylist.append(mc)

# disply objects in list: 
for item in mylist:
    print("-----------------")
    print("name = ", item.name)
    print("name in dict = ", item.valuedict['name'])

The output is:

-----------------
name =  0
name in dict =  2
-----------------
name =  1
name in dict =  2
-----------------
name =  2
name in dict =  2

The name strings are 0, 1 and 2 as expected but name in dictionary is 2 in all 3 objects. Where is the problem and how can it be solved? Thanks for your help.

rnso
  • 23,686
  • 25
  • 112
  • 234
  • 2
    So you want every instance of `MyClass` to have unique values in `valuedict`? You need to add `def __init__(self):` method to your class and specify them as instance attributes e.g. `self.valuedict = {}`. It's worth reading some tutorials on OOP. – roganjosh Nov 19 '17 at 05:39

1 Answers1

3

Currently, valuedict is a class object. I believe what you're going for is to have separate instances, in which case you'll need a constructor (called __init__ in Python).

The corrected class code is as follows (self refers to the instance of the class)

class Myclass:
    def __init__(self):
        self.name = ""
        self.valuedict = {}

So why isn't name acting the same way? In the first for loop, you're defining name, where you're accessing a key of valuedict, which doesn't exist, so you take the "next best thing", the class variable. name doesn't have this problem, as you're initializing it. A better explanation of this can be found here.

jhpratt
  • 6,841
  • 16
  • 40
  • 50
  • 1
    OK. I get it now. I had seen it earlier in docs but forgot to add it here. But then why is `name` coming different in each object? Should that also not be same for all objects? There does appear to be a discrepancy here. – rnso Nov 19 '17 at 05:55
  • For that specific case, it's because you *are* in fact defining an instance variable (albeit implicitly). For the dictionary, you're first accessing a key to the dictionary, which doesn't exist in the instance, so we get it from the class, causing it to be shared. – jhpratt Nov 19 '17 at 06:01
  • @rnso See [this answer](https://stackoverflow.com/a/23137427/2718801) for a better explanation than mine. – jhpratt Nov 19 '17 at 06:13