[英]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
此時, d
和self.d
引用相同的對象。
但是,此后,這兩個類別有所不同:
weird
的通過引用修改對象:
for x in range(3): d[x] = 10+x
由於d
和self.d
引用相同的對象,因此可以通過兩者觀察到變化。
normal
重新綁定d
指向self.d
以外的其他地方:
d = 11
這樣,您就破壞了d
和self.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
是不可變的。 沒什么奇怪的。
有關數據模型的更多信息。
在第一個示例中, d
和self.d
指向可變對象。 當您在對象中的元素上添加十時,您正在修改該可變對象。 因為d
和self.d
指向該對象,所以它們都“看到”結果。
在第二個示例中,您要重新分配d以指向不同的不可self.d
,因此d
和self.d
指向兩個不同的事物。
請注意區別:一種情況下,它們都指向您要更改的同一值,另一種情況下,它們指向兩個不同的值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.