2017-08-14 22 views
1

我有以下代碼,它只使用for循環刪除列表的一半。爲什麼會發生?另外,我應該如何刪除列表中的第一個元素,然後遍歷它?爲什麼在for循環中的del列表[0]只能刪除列表的一半?

list = [1,2,3,4,5,6,7,8,9,10] 
for x in list: 
    print list[0] 
    del list[0] 
print list 

輸出:

1 
2 
3 
4 
5 
[6, 7, 8, 9, 10] 
+1

你改變在循環使用的名單,在副本上工作,以避免這種 – PRMoureu

+2

不要修改你迭代一個列表 - 你的迭代器被搞砸了。另外:不要使用'list'作爲變量名,它會隱藏內建在'list'類型中的pythons。 – AChampion

+0

嘗試:'對於範圍內的x(len(list)):'代替;) – alfasin

回答

3

的問題是,你從列表中刪除,但該列表迭代器不知道,並愉快地處理「剩餘」列表中。

因此,在第一次迭代中,迭代器位於索引0處,並且在下一次迭代時刪除索引0,迭代器返回索引1(在刪除第一個項目之前,索引2處的項目),並刪除索引0.在下一次迭代中,您獲取索引2處的項目(最初位於索引4處,但因爲您刪除了兩個項目,現在位於索引2處),依此類推。最後,只要索引大於列表中剩餘的項目,它就會停止,因爲您爲在原始列表中間(一半)處理的每個項目移除了一個項目。

長話短說:不要修改你正在迭代的列表。


如果你真的想這樣做類似的東西,那麼你可以使用一個while循環:

lst = [1,2,3,4,5,6,7,8,9,10] 
while lst: # as long as the lst contains items 
    print lst[0] 
    del lst[0] 
print lst 

或遍歷一個副本:

lst = [1,2,3,4,5,6,7,8,9,10] 
for x in lst[:]: # [:] makes a shallow copy of a list 
    print lst[0] 
    del lst[0] 
print lst 

注:list是名Python的一個內置函數,所以如果你有一個名字相同的變量,你就會影響這個函數。這就是爲什麼我將變量名改爲lst

2

這裏發生的事情是,你是因爲你迭代它改變了列表,讓我們看看循環迭代

1st iteration: 

pointer 
    | 
    V 
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

現在你刪除列表中的號碼1,但指針也將移動到下一個項目,這就是問題所在

2nd iteration: 

    pointer 
    | 
    V 
[2, 3, 4, 5, 6, 7, 8, 9, 10] 

下一迭代數2將被刪除,該指針將前進。

3rd iteration: 

    pointer 
     | 
     V 
[3, 4, 5, 6, 7, 8, 9, 10] 



4th iteration: 

     pointer 
      | 
      V 
[4, 5, 6, 7, 8, 9, 10] 



5th iteration (last one): 

      pointer 
       | 
       V 
[5, 6, 7, 8, 9, 10] 

現在您打印列表並獲取[6,7,8,9,10]。你可以看到,我所說的實際上是通過將print list[0]行更改爲print list[0], x而發生的,這樣你可以看到指針。

這將是輸出:

1 1 
2 3 
3 5 
4 7 
5 9 
[6, 7, 8, 9, 10] 

可以做些什麼來解決這個問題?以下的任何一個:這意味着該環將具有len(list)迭代

這將使x一個數字(在列表中的項目的索引)(這將是10次迭代)

list = [1,2,3,4,5,6,7,8,9,10] 

for x in range(len(list)): 
    print list[0] 
    del list[0] 
print list 

這將使循環迭代原始列表的副本,因此它將循環10次,這足以刪除列表中的所有項目。

list = [1,2,3,4,5,6,7,8,9,10] 
copy = [1,2,3,4,5,6,7,8,9,10] 

for x in copy: 
    print list[0] 
    del list[0] 
print list 
相關問題