0
class Student():

    NAME = ''
    DICT = {}

    def __init__(self, name):
        self.NAME = name
        self.DICT['name'] = name

    def change_DICT(self, change):
        self.DICT['name'] = change


student_one = Student('Leo')
student_two = Student('Liz')

print ('Student one NAME: ' + student_one.NAME)
print ('Student two NAME: ' + student_two.NAME)
print ('---------------------------------')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))
print ('---------------------------------')
student_one.change_DICT('Tom')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))


>> Student one NAME: Leo
>> Student two NAME: Liz
>> ---------------------------------
>> Student one DICT: {'name': 'Liz'}
>> Student two DICT: {'name': 'Liz'}
>> ---------------------------------
>> Student one DICT: {'name': 'Tom'}
>> Student two DICT: {'name': 'Tom'}

I have been playing with this for hours and still can't wrap my head around it. How does changing DICT of one instance of the class Student changes DICT of all other instances synchronously.

How does this happen and if I really need to use a dict, what is the best way to work around this?

thithien
  • 235
  • 1
  • 12
  • In addition to my answer: I do find it strange that `self.DICT` can still target that class variable, though, so I am not sure why that happens. Perhaps someone else can enlighten us. – Bram Vanroy Jun 01 '18 at 10:21
  • @BramVanroy `self.DICT` doesn't target that class variable, but `self.DICT['name']` does. Your code works even with `DICT` predefined. Thanks for your help! I'll mark this as a duplicate since I found what I needed in the post @Cyber Tailor suggested. – thithien Jun 01 '18 at 15:16

2 Answers2

0

You could achieve your desired output by changing initialization position of class attributes such as DICT and NAME. I will give you the example.

class Student():


    def __init__(self, name):
        self.DICT = {}
        self.NAME = name
        self.DICT['name'] = name

    def change_DICT(self, change):
        self.DICT['name'] = change

student_one = Student('Leo')
student_two = Student('Liz')

print ('Student one NAME: ' + student_one.NAME)
print ('Student two NAME: ' + student_two.NAME)
print ('---------------------------------')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))
print ('---------------------------------')
student_one.change_DICT('Tom')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))

This will give output as:

Student one NAME: Leo
Student two NAME: Liz
---------------------------------
Student one DICT: {'name': 'Leo'}
Student two DICT: {'name': 'Liz'}
---------------------------------
Student one DICT: {'name': 'Tom'}
Student two DICT: {'name': 'Liz'}

Here, You would check dictionary value has been changed.

Deepen Patel
  • 162
  • 3
  • 10
0

You are mixing class variables and instance variables. When you declare a variable outside the constructor (i.e. above __init__) it is a class variable, meaning it is shared. Instead, you only want instance variables, as follows.

class Student():
    def __init__(self, name):
        self.NAME = name
        self.DICT = {'name': name}

    def change_DICT(self, change):
        self.DICT['name'] = change


student_one = Student('Leo')
student_two = Student('Liz')

print ('Student one NAME: ' + student_one.NAME)
print ('Student two NAME: ' + student_two.NAME)
print ('---------------------------------')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))
print ('---------------------------------')
student_one.change_DICT('Tom')
print ('Student one DICT: ' + str(student_one.DICT))
print ('Student two DICT: ' + str(student_two.DICT))
Bram Vanroy
  • 27,032
  • 24
  • 137
  • 239