Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Share global data in Python

Tags:

python

list

class

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?

like image 506
Harry Ma Avatar asked Sep 29 '22 12:09

Harry Ma


1 Answers

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
like image 194
Korem Avatar answered Oct 02 '22 16:10

Korem