2013-05-29 37 views
6

Tôi đã chơi xung quanh với các lớp Python và đến ví dụ sau, trong đó hai biến xuất hiện là các biến lớp tĩnh có hành vi khác nhau khi được sửa đổi.Biến lớp int int vs mảng

Điều gì đang xảy ra ở đây? Bản năng đầu tiên của tôi là cái gì đó phức tạp đang diễn ra với các tham chiếu.

class Foo: 
    a = [] 
    n = 0 
    def bar(self): 
      self.a.append('foo') 
      self.n += 1 

x = Foo() 
print x.a, x.n ([] 0) 
x.bar() 
print x.a, x.n (['foo', 1]) 
y = Foo() 
print y.a, y.n (['foo', 0]) 
y.bar() 
print y.a, y.n (['foo', 'foo'], 1) 
+1

đây là trường hợp tương tự để tìm ra trong python http://stackoverflow.com/questions/101268/hidden-features-of-python#113198 – qwwqwwq

Trả lời

5

Bạn đang đúng - trong trường hợp Foo.a truy cập self.a thực sự truy cập Foo.a, mà được chia sẻ giữa tất cả các trường của Foo. Tuy nhiên, khi bạn cập nhật self.n với += bạn thực sự tạo ra một instance variable cấp trên self rằng bóng tối Foo.n:

>>> import dis 
>>> dis.dis(Foo.bar) 
    5   0 LOAD_FAST    0 (self) 
       3 LOAD_ATTR    0 (a) 
       6 LOAD_ATTR    1 (append) 
       9 LOAD_CONST    1 ('foo') 
      12 CALL_FUNCTION   1 
      15 POP_TOP    

    6   16 LOAD_FAST    0 (self) 
      19 DUP_TOP    
      20 LOAD_ATTR    2 (n) 
      23 LOAD_CONST    2 (1) 
      26 INPLACE_ADD   
      27 ROT_TWO    
      28 STORE_ATTR    2 (n) 
      31 LOAD_CONST    0 (None) 
      34 RETURN_VALUE  

Nói cách khác, khi bạn làm self.a.append('some value') người phiên dịch lấy về a từ bộ nhớ thông qua một tên trên Foo và sau đó biến đổi danh sách mà Foo.a trỏ đến.

Mặt khác, khi bạn làm self.n += 1 người phiên dịch:

  • fetches n từ Foo (vì nó không thể tìm thấy n trên self)
  • Tạo một giá trị mới n + 1
  • Stores sự giá trị mới trong thuộc tính n trên self
+0

Gotcha. Nhiệm vụ gây ra bóng tối là (đối với tôi) bị che khuất phía sau '+ ='. Cảm ơn! – mcamac