迭代失败的具体行为

πόδ*_*κύς 2 python

最近我有人向我询问有关在迭代时更改列表的失礼.他们提出了以下场景(我现在用更好的例子更新了)作为可能的用例,当时可能需要这样做:

>>> 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)

这种行为是否足够常规用于诸如此类的用例?

mgi*_*son 7

从列表中删除项目时,列表中的所有内容都会转移...

[1, 2, 3, 4, 5]
#remove   ^
[1, 2, 3, 5]
Run Code Online (Sandbox Code Playgroud)

如果你在迭代对象的同时执行此操作,并且如果你想要相互删除的项目,那么当你删除第一个时,第二个将转移到它的位置.for循环将继续递增列表中的位置,在该位置拉出一个值,使其跳过碰到的值以取代您删除的项目.

这是一个参考 - 就是这样我们都知道这是记录良好的行为:)


Dim*_*nek 5

你应该使用的是:

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,没有变化

实际上,您的第一个算法会删除每秒零.

你的第二个算法应该不起作用,如果你这样说,也许你没有对它进行足够的测试.