[英]Python Class scope & lists
我仍然是Python的新手,我的OO經驗來自Java。 所以我有一些我用Python編寫的代碼,對我來說非常不尋常,給出以下代碼:
class MyClass():
mylist = []
mynum = 0
def __init__(self):
# populate list with some value.
self.mylist.append("Hey!")
# increment mynum.
self.mynum += 1
a = MyClass()
print a.mylist
print a.mynum
b = MyClass()
print b.mylist
print b.mynum
運行此結果會產生以下輸出:
['Hey!']
1
['Hey!', 'Hey!']
1
很明顯,我希望類變量能夠得到完全相同的數據,並且輸出完全相同......我無法在任何地方找到的是什么使得列表與字符串或數字不同,為什么是列表從后續的第一個實例中引用相同的列表? 很明顯,我可能誤解了某種范圍機制或列表創建機制。
tlayton的答案是故事的一部分,但並不能解釋所有事情。
添加一個
print MyClass.mynum
變得更加困惑:)。 它將打印'0'。 為什么? 因為行
self.mynum += 1
創建一個實例變量,然后增加它。 它不會增加類變量。
mylist的故事是不同的。
self.mylist.append("Hey!")
不會創建列表。 它期望存在具有“追加”功能的變量。 由於實例沒有這樣的變量,因此它最終引用了類中的一個,它確實存在,因為你初始化它。 就像在Java中一樣,實例可以“隱式地”引用類變量。 像“類字段應該由類引用,而不是由實例引用”(或類似的東西;自從我在Java中看到它以來已經有一段時間)的警告將是有序的。 添加一行
print MyClass.mylist
驗證這個答案:)。
簡而言之:您正在初始化類變量並更新實例變量。 實例可以引用類變量,但某些“更新”語句將自動為您創建實例變量。
你在這里做的不僅僅是創建一個類變量。 在Python中,類體中定義的變量既導致類變量(“MyClass.mylist”),又導致實例變量(“a.mylist”)。 這些是單獨的變量,而不僅僅是單個變量的不同名稱。
但是,當以這種方式初始化變量時,初始值僅被計算一次並傳遞給每個實例的變量。 這意味着,在您的代碼中,MyClass的每個實例的mylist變量都指向一個列表對象。
在這種情況下,列表和數字之間的區別在於,與Java一樣,當從一個變量傳遞到另一個變量時,會復制諸如數字之類的原始值。 這會導致您看到的行為; 即使變量初始化僅被計算一次,但是當將0傳遞給每個實例的變量時,也會復制0。 但是,作為一個對象,列表沒有這樣的東西,所以你的append()調用都來自同一個列表。 試試這個:
class MyClass():
def __init__(self):
self.mylist = ["Hey"]
self.mynum = 1
這將導致每次創建實例時單獨評估值。 與Java不同,您不需要在此片段中附帶類體聲明; __init __()中的賦值用作所需的所有聲明。
我認為區別在於+=
是一個賦值(與=
和+
相同),而append
就地改變了一個對象。
mylist = []
mynum = 0
這會在類定義時分配一些類變量。
self.mylist.append("Hey!")
這會通過附加字符串來更改值MyClass.mylist
。
self.mynum += 1
這與self.mynum = self.mynum + 1
,即它分配self.mynum
(實例成員)。 從self.mynum
讀取屬於類成員,因為那時沒有該名稱的實例成員。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.