I am building a project that requires the data to be shared globally. I built a class GlobalDataBase to handle these data, which is like the way in How do I avoid having class data shared among instances? and https://docs.python.org/2/tutorial/classes.html . However, I found something a little bit weird to me. My code is as follows:
class GlobalDataBase:
    a = []
    def copy_to_a(self, value):
        self.a = value  
    def assign_to_a(self, value):
        for idx in range(0, len(value)):
            self.a.append(value[idx])
def test_copy():
    gb1 = GlobalDataBase()
    gb1.copy_to_a([1,2])
    print gb1.a
    gb2 = GlobalDataBase()
    print gb2.a
def test_assign():
    gb1 = GlobalDataBase()
    gb1.assign_to_a([1,2])
    print gb1.a
    gb2 = GlobalDataBase()
    print gb2.a
The output of test_copy is 
[1,2]
[]
The output of test_assign is 
[1,2]
[1,2]
The result of the second method is what I was expecting. But I could not understand why the first method doesn't work. Could anyone explain the difference between these two methods?
a is assigned with a list on GlobalDataBase's declaration. Each instance of GlobalDataBase starts out with a reference to that same list, let's term it the "original" list.
When you do self.a = value in your first example, you replace, for that instance or "self", the reference to the original list with a reference to value, the list you assigned. Any new instance created will still reference the original list, and that's why gb2 prints out an empty list - the original list, and not [1,2] - the new list.
Let's see how that works, using id:
Once declared, GlobalDataBase hold a reference to a:
id(GlobalDataBase.a)
Out[112]: 290675912L #Original
And that same reference is held by any instance we create:
gb1 = GlobalDataBase()
id(gb1.a)
Out[114]: 290675912L #Original
and after copy_to_a, you can see that it changed:
gb1.copy_to_a([1,2])
id(gb1.a)
Out[116]: 290670536L #Changed!
but gb2 still has the original reference:
id(gb2.a)
Out[118]: 290675912L #Original
You said you understood the second example, but for completeness, when you do self.a.append(value[idx]) you append to the original list. As said, new instances have a reference to that list, and "see" that change.
And here we can see the reference does not change:
gb1 = GlobalDataBase()
id(gb1.a)
Out[120]: 290675912L #Original
gb1.assign_to_a([1,2])
id(gb1.a)
Out[122]: 290675912L #Original
gb2 = GlobalDataBase()
id(gb2.a)
Out[124]: 290675912L #Original
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With