2014-11-01 9 views
5

Ich baue ein Projekt, bei dem die Daten global freigegeben werden müssen. Ich habe eine Klasse GlobalDataBase erstellt, um diese Daten zu behandeln, die wie in How do I avoid having class data shared among instances? und https://docs.python.org/2/tutorial/classes.html ist. Allerdings fand ich etwas seltsam für mich. Mein Code ist wie folgt:Gemeinsame Nutzung globaler Daten in Python

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 

Die Ausgabe von test_copy ist

[1,2] 

[] 

Die Ausgabe von test_assign ist

[1,2] 

[1,2] 

Das Ergebnis des zweiten Verfahrens ist das, was ich erwartet hatte. Aber ich konnte nicht verstehen, warum die erste Methode nicht funktioniert. Kann jemand den Unterschied zwischen diesen beiden Methoden erklären?

+1

über Ihre 'assign_to_a' Methode: mehr pythonic wäre' Wert für Element zu schreiben: self.a.append (Element) '. – GingerPlusPlus

Antwort

4

a ist mit einer Liste auf GlobalDataBase Erklärung zugeordnet. Jede Instanz von GlobalDataBase beginnt mit einer Referenz auf die gleiche Liste, nennen wir es die "Original" -Liste.

Wenn Sie self.a = value in Ihrem ersten Beispiel tun, ersetzen Sie für diese Instanz oder "self" den Verweis auf die ursprüngliche Liste mit einem Verweis auf value, die Liste, die Sie zugewiesen haben. Jede neu erstellte Instanz referenziert immer noch die Original Liste, und deshalb druckt gb2 eine leere Liste aus - die ursprüngliche Liste und nicht [1,2] - die neue Liste.

Mal sehen, wie das funktioniert, mit id:

Einmal erklärt, halten GlobalDataBase ein Verweis auf a:

id(GlobalDataBase.a) 
Out[112]: 290675912L #Original 

Und der gleichen Bezug von jedem Fall gehalten wird, wir schaffen:

gb1 = GlobalDataBase() 
id(gb1.a) 
Out[114]: 290675912L #Original 

und nach copy_to_a, können Sie sehen, dass es geändert:

gb1.copy_to_a([1,2]) 
id(gb1.a) 
Out[116]: 290670536L #Changed! 

aber gb2 hat noch die ursprüngliche Referenz:

id(gb2.a) 
Out[118]: 290675912L #Original 

Sie sagten, Sie das zweite Beispiel verstanden, aber der Vollständigkeit halber, wenn Sie self.a.append(value[idx]) tun anhängen Sie an die Original Liste. Wie gesagt, neue Instanzen haben einen Verweis auf diese Liste und "sehen" diese Änderung.

Und hier können wir sehen, die Referenz nicht ändert:

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 
+0

Danke für die Antwort. Ich denke, es ist gut genug für mein Problem. Jetzt verstehe ich beide Methoden gut. –

Verwandte Themen