我是Python新手。這裏有一個關於列表的問題: 據說列表是可變的,元組是不可變的。但是,當我寫:如何理解這個結果?
L1 = [1, 2, 3]
L2 = (L1, L1)
L1[1] = 5
print L2
結果是
([1, 5, 3], [1, 5, 3])
,而不是
([1, 2, 3], [1, 2, 3])
但L2
是一個元組和元組是不可變的。爲什麼當我改變L1
的值時,L2
的值也改變了?
我是Python新手。這裏有一個關於列表的問題: 據說列表是可變的,元組是不可變的。但是,當我寫:如何理解這個結果?
L1 = [1, 2, 3]
L2 = (L1, L1)
L1[1] = 5
print L2
結果是
([1, 5, 3], [1, 5, 3])
,而不是
([1, 2, 3], [1, 2, 3])
但L2
是一個元組和元組是不可變的。爲什麼當我改變L1
的值時,L2
的值也改變了?
該元組是不可變的,但元組內的列表是可變的。你改變了L1(列表),而不是元組。元組包含L1的兩個副本,所以它們都顯示更改,因爲它們實際上是同一個列表。
如果一個對象是「不可變的」,這並不意味着它觸及的所有東西都是不可變的。您可以將可變對象放入不可變對象內,並且這不會阻止您繼續對可變對象進行變異。
該元組沒有得到修改,它仍然包含相同的重複引用列表你給它。
你修改的列表(L1
),不元組(或者更準確地說,不是參考到列表中的元組)。
比如你會不會有能夠做到
L2[1] = 5
因爲元組是一成不變的,你正確的狀態。
所以元組沒有改變,但元組包含引用的列表被修改(因爲兩個條目都是對同一列表的引用,輸出中的兩個值都更改爲5
)。元組中沒有值被改變。
如果您在此情況下將引用看作「指針」,可能會有所幫助。
編輯(在下面的評論基於問題的OP):
關於引用,列表和副本,也許這些例子會有所幫助:
L=range(5)
s = (L, L[:]) # a reference to the original list and a copy
s
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
然後改變L [2]
L[2] = 'a'
給出:
s
([0, 1, 'a', 3, 4], [0, 1, 2, 3, 4]) # copy is not changed
請注意,「2nd」列表沒有更改,因爲它包含副本。
現在,
L=range(5)
我們正在創建的列表的兩個副本,並給予引用的元組
s = (L[:], L[:])
now
L[2] = 'a'
不會影響什麼,但原來的列表L
s
([0, 1, 2, 3, 4], [0, 1, 2, 3, 4])
希望這有幫助。
元組包含兩個引用,每個引用都是相同的列表(不是列表的副本,正如您所預料的那樣)。因此,列表中的更改仍然會顯示在元組中(因爲元組只包含引用),但是元組本身沒有被更改。因此,不可侵犯性不受侵犯。
如果我寫L1 = [1,2,3] A = L1 [1] L1 [1] = 5 打印A – Rachaely
@ user1641021:在該片段中,首先製作一個列表並將其命名爲L1。然後,將名稱A綁定到L1 [1]所涉及的對象,該對象是整數2.然後將L1的第二個元素更改爲5,然後打印A,它仍然是2;你「指出」在整數2,而不是「L1的第二個元素」。 – DSM
但是,如果我寫L1 = [1,2,3] A = L1 [1] L1 [1] = 5 打印A結果將是2而不是5.是否因爲'L1 [1]'包含L1的副本,而不是L1的參考,這樣即使L1改變了它的值,L1 [1]也不會? – Rachaely
從Python文檔(http://docs.python.org/reference/datamodel.html),請注意:
不可變容器對象,它包含了一個可變 對象的引用的值當後者的價值改變時可以改變;然而容器 仍然被認爲是不可變的,因爲它所包含的對象集合不能被 改變。因此,不變性與具有不變的價值並不完全相同,它更加微妙。
你說得對,元組是不可改變的:L2是兩個引用的不可變元組L1(不,因爲它可能會首先出現,兩個列表的元組),而L1並不是一成不變的。當你改變L1時,你不會改變L2,只是L2引用的對象。
使用deepcopy的代替=
:
從拷貝導入deepcopy的
L2 = deepcopy的(L1)
元組是不可變的手段只有一兩件事 - 一旦你構造一個元組,不可能修改它。另一方面,列表可以添加元素,從中刪除元素。但是,元組和列表都與它們包含的元素有關,但與這些元素的內容無關。
在Python中,這與元組或列表無關,當你添加一個簡單的值,比如一個int值時,它被表示爲is,但是像列表,元組或其他任何類的複雜值類型的對象是總是存儲爲參考。
如果你要你的元組轉換爲set()
,你會得到那可能會讓你大吃一驚的錯誤消息,但鑑於上述,應該是有意義:
>>> L=range(5)
>>> s = (L, L[:]) # a reference to the original list and a copy
>>> set(1, 2, s)
>>> set((1, 2, s))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
由於值set
絕決一旦它們被添加到集合中,則包含在不可變元組s
內的任何可變值都將提升TypeError
。
這使得看起來'int'不是'通過引用存儲'的方式與「複數值」相同,而是「表示爲」。但是'int'與'tuple'完全相同。 – DSM
看起來像你創建一個視圖,而不是一個深層複製? –