簡體   English   中英

Python為什么在Class名稱空間中對列表和整數進行不同的處理?

[英]Why does Python treat lists and integers differently in Class namespace?

這兩個類定義的結構相同,只是在weird()類定義中,屬性“ d”是一個列表,而在normal()類定義中,它是一個int。 我不明白為什么weird()類會導致self.d = d,而對於normal()類卻並非如此。 在這種情況下,為什么Python對待int和list有所不同?

class weird:
    def __init__(self):
        d = [1,2,3]
        self.d = d
        for x in range(3):
            d[x] = 10+x 
        print "d =", d
        print "self.d =", self.d

class normal:
    def __init__(self):
        d = 1
        self.d = d
        d = 11
        print "d =", d
        print "self.d =", self.d

當我運行代碼時,我得到

>>> a=weird()
d = [10, 11, 12]
self.d = [10, 11, 12]
>>> b=normal()
d = 11
self.d = 1

您將分配與對象的變異混淆了。

在一種方法中,您為d分配了新值,將其指向的值更改為:

d = 11

但是在另一種方法中,您更改了d 包含的值:

d[x] = 10 + x

注意那里的[x] 從本質上講,您是在告訴python執行以下操作:

d.__setitem__(x, 10 + x)

指向列表的變量d的值永遠不會更改。 d引用的列表中的值會發生變化。

請看一下我之前的答案,其中更詳細地介紹了這兩個語句之間的區別: Python列表不反映變量change

實際上,這里的語言是完全一致的。 您正在觀察兩種不同的行為,因為您正在執行兩種根本不同的操作。

__init__的前兩行在兩個類中都是一致的(不同類型的d除外):

class WeirdOrNormal:
    def __init__(self):
        d = ... # 1 or [1, 2, 3]
        self.d = d

此時, dself.d引用相同的對象。

但是,此后,這兩個類別有所不同:

  1. weird的通過引用修改對象:

     for x in range(3): d[x] = 10+x 

    由於dself.d引用相同的對象,因此可以通過兩者觀察到變化。

  2. normal重新綁定d指向self.d以外的其他地方:

     d = 11 

    這樣,您就破壞了dself.d之間的鏈接。 他們現在是完全獨立的。

如果您要更改weird以重新綁定引用,就像normal一樣,您會看到兩個類的行為彼此一致:

class notweird:
    def __init__(self):
        d = [1,2,3]
        self.d = d
        d = [10+x for x in self.d]
        print "d =", d
        print "self.d =", self.d

a = notweird()

此打印

d = [11, 12, 13]
self.d = [1, 2, 3]

對於文檔:

價值可以改變的對象被認為是可變的。 創建后其值不可更改的對象稱為不可變的。 (當更改可變對象的值時,包含對可變對象的引用的不可變容器對象的值可以更改;但是該容器仍被認為是不可變的,因為它所包含的對象的集合無法更改。因此,不可變性並不是嚴格意義上的與具有不變的值一樣,它更加微妙。)對象的可變性由其類型決定; 例如,數字,字符串和元組是不可變的,而字典和列表則是可變的。

在您的情況下, list是可變的, int是不可變的。 沒什么奇怪的。

有關數據模型的更多信息。

在第一個示例中, dself.d指向可變對象。 當您在對象中的元素上添加十時,您正在修改該可變對象。 因為dself.d指向該對象,所以它們都“看到”結果。

在第二個示例中,您要重新分配d以指向不同的不可self.d ,因此dself.d指向兩個不同的事物。

請注意區別:一種情況下,它們都指向您要更改的同一值,另一種情況下,它們指向兩個不同的值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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