2014-02-15 25 views
11

所以我在Python中遇到了很奇怪的東西。我試着給自己添加一個對列表的引用。該代碼可能有助於證明我說的比我能表達的更好。我正在使用IDLE編輯器(交互模式)。對本身的列表遞歸引用

>>>l=[1,2,3] 
>>>l.append(l) 
>>>print(l) 
[1,2,3,[...]] 
>>>del l[:-1] 
>>>print(l) 
[[...]] 

到目前爲止輸出如預期。但是當我這樣做。

y=l[:] 
print(y) 

對我來說,似乎輸出應該

[[...]] 

但它是

[[[...]]] 

顯然不是創建表的副本,它把一個參考列表y。

y [0]是l返回True。我似乎無法找到一個很好的解釋。有任何想法嗎?

回答

8

區別僅在於列表顯示的方式。即y的價值正是你所期望的。

在列表中顯示的事實結果是,與ly不是自引用列表方式的不同:

l[0] is l 
=> True 
y[0] is y 
=> False 

y不是自我參照,因爲y沒有引用y。它引用了l,它是自引用的。

因此,將列表翻譯爲字符串的邏輯在y上比在l上工作時檢測到潛在的無限遞歸更深一級。

3

這是完美的預期。當Python打印遞歸列表時,它會檢查它正在打印的列表是否尚未遇到,並且是否已打印[...]。重要的一點是,它不會測試等於(如==),但身份(如is)。因此,

  • 當您打印l = [l]。您有l[0] is l返回True,因此它打印[[...]]

  • now y = l[:]製作l的副本,因此y is l返回False。所以這裏發生了什麼。它開始打印y因此它打印[??? ]其中???y[0]的打印替換。現在y[0]l而不是y。所以它打印[[???]]???取代y[0][0]。現在已經遇到y[0][0]l。所以它最終打印[...]給予[[[...]]]

+0

你能否詳細說明一下?你失去了我在**「它開始打印y:[???] ..... ** – Guy

+0

另外如果我真的想要一份清單的副本?我知道我可以在這種情況下對y做同樣的處理,但爲了討論的緣故,我有辦法做到這一點嗎? – Guy

+0

@Sabyasachi:這樣更清楚嗎? – hivert

1

切片生成項目列表。只有一個項目列表「l」。所以,我們有一個元素的新列表 - 列表「l」。

2

您需要有一個完整副本的對象。你需要使用copy.deepcopy,你會看到預期的結果。

>>> from copy import deepcopy 
>>> l=[1,2,3] 
>>> l.append(l) 
>>> print(l) 
[1, 2, 3, [...]] 
>>> del l[:-1] 
>>> print(l) 
[[...]] 
>>> y=deepcopy(l) 
>>> print(y) 
[[...]] 
>>> y[0] is l 
False 
>>> 

當您使用切片表示法複製的清單,內引用保留這會導致你觀察到的行爲。