在周遊list的時候,删除符合條件的資料,結果不符合預期
num_list = [1, 2, 2, 2, 3]print(num_list)for item innum_list:if item == 2:
num_list.remove(item)else:print(item)print(num_list)
結果是
[1, 2, 2, 2, 3]1[1, 2, 3]
或者有:
num_list = [1, 2, 3, 4, 5]print(num_list)for i inrange(len(num_list)):if num_list[i] == 2:
num_list.pop(i)else:print(num_list[i])print(num_list)
結果報錯:
[1, 2, 3, 4, 5]
Traceback (most recent call last):1
4
5File"tes.py", line 5, in
if num_list[i] == 2:
IndexError: list index out of range
Process finished with exit code1
原因是,删除list中的元素後,list的實際長度變小了,但是循環次數沒有減少,依然按照原來list的長度進行周遊,是以會造成索引溢出。
1.把清單拷貝,然後對原清單進行删除操作就沒問題了
num_list = [1, 2, 2, 2, 3]print(num_list)for item innum_list[:]:if item == 2:
num_list.remove(item)else:print(item)print(num_list)
結果:
[1, 2, 2, 2, 3]1
3[1, 3]
num_list[:]是對原始的num_list的一個拷貝,是一個新的list,是以,我們周遊新的list,而删除原始的list中的元素,則既不會引起索引溢出,最後又能夠得到想要的最終結果。此方法的缺點可能是,對于過大的list,拷貝後可能很占記憶體。
2.從後往前周遊清單,删除
3.filter函數
例子 list中去空字元(配合lambda表達式):
condition = lambda t: t != "" (判斷符合條件很複雜就不能使用lambda,自己寫方法吧)
filter_list = list(filter(condition, list)
Python的List的底層是實作是一個PyObject*數組。如果每次增加一個元素都擴張記憶體的話效率太低,在增加元素的時候是以會有預申請記憶體。同理删除元素的時候也不是馬上就減小記憶體空間,他會按照一定的政策減小。而這種減小不太好預測。
再加上删除後索引如何調整并沒有明确定義。比如一個長度為3的List你删除了第2個那麼第三個下标應該是2還是3,等等可能會引發歧義。如果這個時候記憶體達到了需要減小的條件,疊代器就不太好判斷新的索引究竟是多少。
是以Python為了通用性和安全性考慮就禁止在周遊時删除元素了。