簡體   English   中英

Python類范圍和列表

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM