2015-02-24 53 views
0

我沒有想到這會起作用,因爲我修改了正在迭代的對象,但我沒有想到它會以這種方式失敗。我實際上預計會有一個例外被提出。迭代列表時發生意外的行爲

>>> x = [1, 2, 3] 
>>> for a in x: 
... print a, x.pop(0) 
... 
1 1 
3 2 
>>> x 
    [3] 

隨着稍大範圍:

>>> x = [1, 2, 3, 4] 
>>> for a in x: 
... print a, x.pop(0) 
... 
1 1 
3 2 
>>> x 
    [3, 4] 

一點點仍然較大:

>>> x = [1, 2, 3, 4, 5] 
>>> for a in x: 
... print a, x.pop(0) 
... 
1 1 
3 2 
5 3 
>>> x 
    [4, 5] 

這就像for循環創建從列表中產生,但比較「索引」與列表的長度以決定迭代何時結束。

它似乎仍然應該產生一個例外,但不是這種奇怪的行爲。有沒有理由不引發異常?

+0

一個非常有趣的問題,因爲突變字典被重複*會引發異常。 – 2015-02-24 21:48:10

+0

不重複。那些問什麼會發生,這是爲什麼Python允許它發生。 – 2015-02-24 21:49:12

+0

他正在遍歷列表,而不是字典 – RPGillespie 2015-02-24 21:50:33

回答

0

正如你直覺的那樣,for循環在內部使用索引,每次迭代時增加1,當索引超過列表長度時停止。這是如何爲列表定義迭代的。它以其他方式定義爲其他類型,您可以通過執行__iter__來爲自己的類定義它。

在迭代列表時修改列表是合法的,而且一旦瞭解它的工作原理就可以預測。刪除一個或多個項目時,項目向下移動到較低索引後,如果刪除項目的索引小於或等於循環的當前索引,則循環遞增索引時最終跳過項目。

有許多解決方案:以相反順序迭代,遍歷副本,創建要刪除的索引列表並單獨執行,建立新列表而不是修改現有列表,使用while循環如果您有條件地移除項目,而不是if聲明......也可能有其他方法。

+0

我還在python網站上週末發現了這些文檔https://docs.python.org/2/reference/compound_stmts.html#for有趣的是,不是在for語句下。 – boatcoder 2015-02-27 21:33:40

相關問題