Python編程整理:通過修改實例類變量改變類的類變量的問題(成因:類變量為可變變量)


先上代碼,

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]

 

那么,結論就是,當類變量為可變變量,並且實例在修改類變量時使用了不更改變量內存地址的方法對類變量進行了修改,此時是會同時影響類中的類變量的。

在日常應用中,在使用可變變量的類變量作為實例之間傳遞數據媒介時,修改實例中類變量的同時一定要切記檢查是否會修改類中的類變量。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM