先上代碼, class C1(object): class_variable = 1 class C2(object): class_variable = [] object1 = C1() object2 = C2() print(C1.class_variable) # 1 print(obje ...
先上代碼,
class C1(object): class_variable = 1 class C2(object): class_variable = [] object1 = C1() object2 = C2() print(C1.class_variable) # 1 print(object1.class_variable) # 1 object1.class_variable = 20 print(object1.class_variable) print(C1.class_variable) # 20 # 1
由此可見,在類變數為不可變變數(例子中為整數)時,對類C1產生的實例object1使用點運算更改object1的類變數後發現,
實例object1中的類變數產生了更改,而類C1中的類變數沒有被更改。
這一點比較好理解。在類產生實例的同時,實例會從類中獲取其內容的備份。因此,對實例進行修改,會更改實例中的內容而不會影響類中的內容。
要註意的是,當類變數是不可變變數時,遵循不可變變數的特性,實例中類變數的改變是將實例中的類變數指向一個新的記憶體地址。這點對理解之後的內容至關重要。
以下為測試,
class C1(object): class_variable = 1 class C2(object): class_variable = [] object1 = C1() object2 = C2() print(id(object1.class_variable)) print(id(C1.class_variable)) # 140719616585984 # 140719616585984 object1.class_variable = 20 print(id(object1.class_variable)) print(id(C1.class_variable)) # 140719616586592 # 140719616585984
那麼,當類變數為可變變數時會怎樣呢?
class C1(object): class_variable = 1 class C2(object): class_variable = [] object1 = C1() object2 = C2() print(object2.class_variable) print(C2.class_variable) # [] # [] object2.class_variable = [1, 2] print(object2.class_variable) print(C2.class_variable) # [1, 2] # []
在上面的代碼中,使用了對object2的類變數直接賦值新列表的方式來更改類變數的數據,此時,object2中的類變數會指向一個新的記憶體地址,因此依然不會改變C2中的類變數的初始值。
但是,如果這樣:
class C1(object): class_variable = 1 class C2(object): class_variable = [] object1 = C1() object2 = C2() print(object2.class_variable) print(C2.class_variable) # [] # [] object2.class_variable.append(1) print(object2.class_variable) print(C2.class_variable) # [1] # [1]
此時就會發現,當使用append函數對object2的類變數進行修改後,類C2中的類變數也神奇得被修改了!!
那麼成因也可以歸結為可變變數的特殊性。
我們先查一下兩者的記憶體地址。
object2.class_variable.append(1) print(id(object2.class_variable)) print(id(C2.class_variable)) # 1616354562632 # 1616354562632
沒錯,果然兩者指向的記憶體地址是相同的。
這是因為,在使用append函數時,並不會改變實例object2的類變數的指向地址。因此,在更改該地址上列表的內容後,指向相同地址的類C2的類變數也一起被修改了。
在列表這個可變變數中,除了append函數,直接修改列表中的元素也會得到這樣的結果,比如:
class C2(object): class_variable = [1, 2, 3] object2 = C2() object2.class_variable[1] = 20 print(object2.class_variable) print(C2.class_variable) # [1, 20, 3] # [1, 20, 3]
那麼,結論就是,當類變數為可變變數,並且實例在修改類變數時使用了不更改變數記憶體地址的方法對類變數進行了修改,此時是會同時影響類中的類變數的。
在日常應用中,在使用可變變數的類變數作為實例之間傳遞數據媒介時,修改實例中類變數的同時一定要切記檢查是否會修改類中的類變數。