標籤:
之前在用python開發一個項目,發現一個bug,就是同由一個類產生的兩個執行個體之間的資料竟然會相互影響,這讓我非常不解。後來聯想到java的類有類變數也有執行個體變數,因此翻閱了相關資料,發現python也有類似的類變數和執行個體變數,比如下面的代碼中:
class A:
x = 0
def __init__(self):
self.y = 0
x就是類變數,y就是執行個體變數。
原則上是沒有錯的,但是實際用的時候就發現一些噁心的問題(也就是我找了三天的bug)。。。比如下面的代碼:
class A:
x = []
y = 0
def __init__(self):
pass
def add(self):
self.x.append(’1’)
self.y+=1
a=A() print a.x,a.yprint A.x,A.y
a.add()print a.x,a.yprint A.x,A.y
b=A() print b.x,b.yprint A.x,A.y
這裡很明顯x和y都是類變數,add的作用是分別對x和y做出修改。然後構造一個執行個體a,對執行個體a的值進行修改,最後構造執行個體b。
本以為這個結果是顯而易見的,然而他輸出的結果卻是:
[] 0
[] 0
[’1’] 1
[’1’] 0
[’1’] 0
[’1’] 0
問題在哪?明明x和y都是類變數,在第二組print中為什麼a.x和b.x一樣,但是a.y和b.y就是不一樣呢?
想了半天悟了一個道理。。。就是對於python來說,類變數的確是所有類共有的東西。但是那是在我們用的同一個引用的情況下,比如對於[]對象的append方法就是公用一個類變數了;但是對於指派陳述式來說,如果在類中對類變數使用了指派陳述式,那麼python就會產生一個該對象的副本,以後的操作都是基於這個副本而不會對原來的類對象造成影響。這樣就解釋的通上面的現象了。
那麼為了杜絕自己忘記類變數和執行個體變數的區別導致本不想公用變數的時候公用了變數,最好的辦法就是在每個類中使用變數的時候重新初始化一下,這樣就不會導致意外了
來源:Myths的個人部落格
Python類變數和成員變數使用中有哪些注意事項?