運行下面的示例代碼:
class S:
i = 0
a = []
def __init__(self):
self.i = 1
self.a.append(1)
s1 = S()
print((s1.i, s1.a))
s2 = S()
print((s2.i, s2.a))
輸出將是:
(1, [1])
(1, [1, 1])
我的問題是為什么 s2 的 int Si 重置為 0 但串列 Sa 沒有重置為空?我認為這與不可變 int 與可變串列有關,但有人可以幫助表達在兩個 init 呼叫期間兩個類變數發生了什么的更多細節嗎?謝謝!
uj5u.com熱心網友回復:
因此,當您呼叫s1.i或時,您正在更改實體屬性s1.a。要更改類屬性,請嘗試以下操作:
S.i = 1
S.a.append(1)
在您的建構式中,您初始化self.a和self.i. 這將創建屬于類的每個實體的實體屬性。
a和在建構式外宣告的i是類屬性,并由所有實體共享。
無論使用哪個屬性,原因s1.a和S.a更新都是因為串列是可變的,并且實體和類變數都是對同一串列的參考。
uj5u.com熱心網友回復:
self.i = 1
相當于
self.i = self.i 1
當實體變數不存在時,在類上查找值,所以在這種場景下,相當于
self.i = S.i 1
定義后self.i,任何進一步的值查找都在實體變數上,而不是在類變數上。所以在這條線之后,你有S.i = 0and s1.i = 1。既然S.i不修改,s2.i也就變成1.
另一方面,
self.a.append(1)
不會創建新的實體變數,而是將元素附加到現有的類變數。
uj5u.com熱心網友回復:
這段特定代碼的撰寫方式抽象了 Python 在幕后所做的一些事情,所以讓我們來看看它。
當您定義類并像在代碼開頭那樣定義任何函式之外的變數時,它會創建類屬性。這些在您的類的所有實體之間共享(在您的情況下,s1并且s2都共享對您的i物件和您的a物件的相同參考)。
當您初始化類時,您正在呼叫該__init__函式,該函式在您的代碼中首先呼叫self.i = 1,我認為這是大多數混亂的來源。在 Python 中,整數是不可變的,因此它們不能被覆寫。通過呼叫 =,您將洗掉對舊i變數的參考并創建一個參考記憶體中不同位置的新變數。但是因為你現在在你的類中的一個函式中,它被定義為一個實體屬性。實體屬性不會在類的不同實體之間共享。
但是,串列是可變的。所以當你追加1到你的串列時,你并沒有創建一個新的實體變數,所以它保持對類屬性的相同參考,因此當你第二次初始化你的類時,它會將它添加到已經存在的類屬性中創建第一個實體時填充一次。
uj5u.com熱心網友回復:
class S:
i = 0
a = []
def __init__(self):
self.i = 1
self.a.append(1)
定義的串列a = []是類屬性。它在定義類時實體化,并保持相同的串列物件。此類的任何實體都將參考一個串列。
如果您想為每個新實體創建一個空串列,請將串列定義移至__init__方法內:
class S:
i = 0
def __init__(self):
self.a = []
self.i = 1
self.a.append(1)
結果:
>>> s1 = S()
>>> print((s1.i, s1.a))
(1, [1])
>>>
>>> s2 = S()
>>> print((s2.i, s2.a))
(1, [1])
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/478441.html
標籤:Python
