2014-11-01 16 views
5

Tôi đang xây dựng một dự án yêu cầu dữ liệu được chia sẻ trên toàn cầu. Tôi đã xây dựng một lớp GlobalDataBase để xử lý các dữ liệu này, giống như cách trong How do I avoid having class data shared among instances?https://docs.python.org/2/tutorial/classes.html. Tuy nhiên, tôi đã tìm thấy một chút gì đó kỳ lạ đối với tôi. Mã của tôi là như sau:Chia sẻ dữ liệu toàn cầu bằng 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 

Kết quả của test_copy

[1,2] 

[] 

Kết quả của test_assign

[1,2] 

[1,2] 

Kết quả của phương pháp thứ hai là những gì tôi mong đợi. Nhưng tôi không thể hiểu tại sao phương pháp đầu tiên không hoạt động. Bất cứ ai có thể giải thích sự khác biệt giữa hai phương pháp này?

+1

Về 'phương pháp assign_to_a' của bạn: hơn pythonic sẽ được để viết' cho các phần tử trong giá trị: self.a.append (element) '. – GingerPlusPlus

Trả lời

4

a được chỉ định với một danh sách trên tờ khai của GlobalDataBase. Mỗi trường hợp của GlobalDataBase bắt đầu bằng một tham chiếu vào cùng một danh sách đó, hãy đặt tên cho danh sách "gốc".

Khi bạn làm self.a = value trong ví dụ đầu tiên, bạn thay thế, cho trường hợp đó hoặc "tự", tham chiếu đến danh sách gốc có tham chiếu đến value, danh sách bạn đã chỉ định. Bất kỳ cá thể mới nào được tạo vẫn sẽ tham chiếu đến danh sách gốc gốc và đó là lý do tại sao gb2 in ra một danh sách trống - danh sách gốc và không phải [1,2] - danh sách mới.

Hãy xem cách mà làm việc, sử dụng id:

Khi tuyên bố, GlobalDataBase giữ một tham chiếu đến a:

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

Và tham chiếu tương tự được tổ chức bởi bất kỳ trường hợp chúng ta tạo ra:

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

và sau copy_to_a, bạn có thể thấy rằng nó đã thay đổi:

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

nhưng gb2 vẫn có tham khảo bản gốc:

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

Bạn nói rằng bạn hiểu ví dụ thứ hai, nhưng cho đầy đủ, khi bạn làm self.a.append(value[idx]) bạn nối thêm vào danh sách gốc. Như đã nói, các phiên bản mới có tham chiếu đến danh sách đó và "xem" thay đổi đó.

Và ở đây chúng ta có thể thấy các tài liệu tham khảo không thay đổi:

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

Cảm ơn câu trả lời. Tôi nghĩ nó đủ tốt cho vấn đề của tôi. Bây giờ tôi hiểu cả hai phương pháp tốt. –

Các vấn đề liên quan