1. 程式人生 > >python 類屬性 、實例屬性,可變數據結構作為類屬性需要註意的地方

python 類屬性 、實例屬性,可變數據結構作為類屬性需要註意的地方

新的 tool gpo 聲明 info 必須 電影 title img

有一個大笨豬,按java寫觀察者模式,java寫得是直接在類名下聲明一個實例屬性(不加static的),他直接翻譯成python後,也是直接寫在類名下面,這就是大坑了。

java裏面在類名下面聲明的帶static為類屬性,不帶static為實例屬性,python如果直接寫在類名下面的屬性,一律都是類屬性,實例屬性一般都是在init裏面寫的,帶self字眼的變量。

技術分享圖片

技術分享圖片
#coding:utf-8

class A():
    x_list = []

a1 = A()
a1.x_list.append(1)
a2 = A()
print(‘第一個結果 -->‘,a2.x_list)



class B():
    x = 0

b1 = B()
b1.x =1
b2 = B()
print(‘第二個結果‘,b2.x)



class C():
    x = 0

c1 = C()
C.x =1
c2 = C()
print(‘第二個結果‘,c2.x)
技術分享圖片

運行結果是這樣的。

技術分享圖片

對比 A B C三個類可以發現,類屬性自己一份,實例屬性默認等於類屬性。

比如B類,實例b1的x默認等於0,當賦值為1時候,b1的x就等於1了,此時B類的屬性x仍然等於0,b2實例的屬性x也是等於0。

c類,直接改變C類的x屬性,則C的x變為1了,如果實例化一個新的c2,默認就等於1了。

B和C的這種操作是很多案例上都有的,爛大街了,一定需要查看常見容易錯誤的案例。

最主要還是A類,A類的x_list是一個列表,列表是可變數據結構,用可變次數據結構作為類屬性,就要很小心了,即使是用實例a1操作x_list,仍然會影響A的屬性x_list和a2的屬性x_list。當可變元素作為類屬性時候,操作 a.x_list和A.x_list是等效的,都是互相影響的。

不可變數據結構例子:

a_str = ‘hello’

b_str = a_str

b_str = a_str + ‘world‘

最終a的值是hello ,b的值是hello world。

可變的數據結構例子:

a_list = [‘hello‘]

b_list = a_list

b_list + = [‘world‘]

最終a_list和b_list的值都是[‘hello‘, ‘world‘]

回到題目就是,在觀察者模式中,如果把訂閱者添加到類屬性x_lsit列表,那麽所有的發布者都共享了所有的訂閱者。

比如小明、小軍訂閱了蒼老師,小紅 小黃訂閱了波老師,但蒼老師更新電影時候,由於共享了訂閱者,導致小紅和小黃也收到新片通知了,這顯然是個錯誤。

所以蒼老師和波老師的x_list必須是獨立的,需要寫在__init__裏面,寫成self.x_list,這樣蒼老師和波老師的x_list就都是獨立的了,添加訂閱者到蒼老師的列表,波老師的列表不會跟著變化。

python 類屬性 、實例屬性,可變數據結構作為類屬性需要註意的地方