2014-11-01 11 views
5

Buduję projekt, który wymaga globalnego udostępniania danych. Zbudowałem klasę GlobalDataBase do obsługi tych danych, która jest podobna do tej z How do I avoid having class data shared among instances? i https://docs.python.org/2/tutorial/classes.html. Jednak znalazłem dla mnie coś dziwnego. Mój kod wygląda następująco:Udostępnianie danych globalnych w języku 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 

Wyjście test_copy jest

[1,2] 

[] 

Wyjście test_assign jest

[1,2] 

[1,2] 

Efektem drugiej metody jest to, czego się spodziewałem. Ale nie mogłem zrozumieć, dlaczego pierwsza metoda nie działa. Czy ktokolwiek mógłby wyjaśnić różnicę między tymi dwoma metodami?

+1

O swojej 'metody assign_to_a': więcej pythonic byłoby napisać' dla elementu wartość: self.a.append (element) '. – GingerPlusPlus

Odpowiedz

4

a jest przypisany do listy na deklaracji GlobalDataBase. Każde wystąpienie GlobalDataBase rozpoczyna się od odniesienia do tej samej listy, nazwijmy to "oryginalną" listą.

Kiedy wykonasz self.a = value w pierwszym przykładzie, zastępujesz, dla tej instancji lub "siebie", odniesienie do oryginalnej listy z odniesieniem do value, przypisaną listą. Każda utworzona nowa instancja nadal będzie odwoływać się do oryginalnej listy , dlategodrukuje pustą listę - oryginalną listę, a nie [1,2] - nową listę.

Zobaczmy, jak to działa, używając id:

Raz zadeklarowany, GlobalDataBase posiadać odniesienie do a:

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

I to samo odniesienie znajduje się w posiadaniu każdym przypadku tworzymy:

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

i po copy_to_a widać, że uległo zmianie:

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

ale gb2 nadal ma oryginalne odwołanie:

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

Mówiłeś rozumieć drugiego przykładu, ale pod względem kompletności, kiedy robisz self.a.append(value[idx]) dołączeniu do oryginalnej listy . Jak już wspomniano, nowe instancje odwołują się do tej listy i "widzą" tę zmianę.

I tu widzimy odniesienie nie zmienia:

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

Dzięki za odpowiedź. Myślę, że to wystarczająco dobre dla mojego problemu. Teraz dobrze rozumiem obie metody. –

Powiązane problemy