最近我有人向我询问有关在迭代时更改列表的失礼.他们提出了以下场景(我现在用更好的例子更新了)作为可能的用例,当时可能需要这样做:
>>> jersey_numbers = [4, 2, 3, 5, 1] # list of places in a race
>>> for jersey_number in jersey_numbers:
if jersey_number == 2: # disqualify jersey number 2 for a false start
t.remove(jersey_number)
>>> t
[4, 3, 5, 1] # jersey number 3 is now in second place
Run Code Online (Sandbox Code Playgroud)
这种行为是否足够常规用于诸如此类的用例?
从列表中删除项目时,列表中的所有内容都会转移...
[1, 2, 3, 4, 5]
#remove ^
[1, 2, 3, 5]
Run Code Online (Sandbox Code Playgroud)
如果你在迭代对象的同时执行此操作,并且如果你想要相互删除的项目,那么当你删除第一个时,第二个将转移到它的位置.for循环将继续递增列表中的位置,在该位置拉出一个值,使其跳过碰到的值以取代您删除的项目.
这是一个参考 - 就是这样我们都知道这是记录良好的行为:)
你应该使用的是:
t = filter(None, t) # or
t = [x for x in t if x]
Run Code Online (Sandbox Code Playgroud)
或者如果您的情况实际上更复杂:
t = filter(lambda x: x != something, t) # or
t = [x for x in t if x != something]
Run Code Online (Sandbox Code Playgroud)
顺便说一句,remove删除第一个匹配的元素,不一定是你x当前指向的元素,尽管在你的简单案例行为中是相同的.
会发生什么,当你迭代列表时你删除元素,迭代器不知道它,让我们说你的列表是[1,0,0,2]:
1接下来是迭代器,没有变化0,你删除一些0是第一个,列出改变大小,现在迭代器指向第二个零,下一个2,没有变化实际上,您的第一个算法会删除每秒零.
你的第二个算法应该不起作用,如果你这样说,也许你没有对它进行足够的测试.