Python 如果在迭代列表时从列表中删除元素,为什么会跳过它?

Python 如果在迭代列表时从列表中删除元素,为什么会跳过它?,python,list,python-2.7,Python,List,Python 2.7,我试过这个: list = [[1], [2], [], [4], [5], [], [], [], [9]] for e in list: if e == []: list.remove(e) 然后我得到了 >>> list [[1], [2], [4], [5], [], [9]] 发生什么事了 for e in list: if e == []: list.remove(e) 在这种情况下,当e为空列表时,该特定值将从

我试过这个:

list = [[1], [2], [], [4], [5], [], [], [], [9]]
for e in list:
    if e == []:
        list.remove(e)
然后我得到了

>>> list
[[1], [2], [4], [5], [], [9]]
发生什么事了

for e in list:
    if e == []:
        list.remove(e)
在这种情况下,当
e
为空列表时,该特定值将从列表中删除。因此,列表中的下一个元素将成为当前元素。在下一次迭代中,下一个元素取自列表。由于实际的下一个元素已向后移动,因此将采用下一个实际的下一个元素。因此,如果存在多个连续匹配,则有可能跳过元素

在您的情况下,假设
e
位于
[]
后面的
[2]

[[1], [2], [], [4], [5], [], [], [], [9]]
            ^
因为它是一个空列表,所以它将被删除,列表将变为空

[[1], [2], [4], [5], [], [], [], [9]]
            ^
在下一次迭代中,将拾取下一个元素,因此

[[1], [2], [4], [5], [], [], [], [9]]
                 ^
在本例中,我们无声地跳过了
[4]
。但是,由于它是在输出中预期的,所以没有任何区别。但是考虑<<代码> [COD] > <代码> > [5 ] < /代码>,
[[1], [2], [4], [5], [], [], [], [9]]
                      ^
这将被删除,因此列表如下所示

[[1], [2], [4], [5], [], [], [9]]
                      ^
>>> [e for e in list if e]
[[1], [2], [4], [5], [9]]
现在,在下一次迭代中,
e
将引用下一个元素,即

[[1], [2], [4], [5], [], [], [9]]
                          ^
因此,当前的空列表被删除,
[9]
成为当前元素。这就是跳过其中一个空列表的方式

注意:底线是,在迭代容器时,不要从容器中删除项目

解决方案1:

最常见的技术是使用正在迭代的列表的副本,因为迭代和实际列表将在循环中修改。比如说,

for e in list[:]:       # `list[:]` is a shallow copy of `list`
    if e == []:
        list.remove(e)
解决方案2:(首选方法)

使用列表理解和过滤条件创建一个新列表,如下所示

[[1], [2], [4], [5], [], [], [9]]
                      ^
>>> [e for e in list if e]
[[1], [2], [4], [5], [9]]

注意消除空列表的方式。Python中的空列表被视为假值。因此,
if e
只有在
e
中至少有一个元素时才会计算为Truthy。

独立于语言的解决方案:向后迭代

l = [[1], [2], [], [4], [5], [], [], [], [9]]
for e in reversed(l):
    if e == []:
        l.remove(e)

内置函数
过滤器
也提供此功能。作为列表理解的替代方法,您可以使用
过滤器(无,列表)
@nelfin True,但在Python@nelfin列表理解比
过滤器
映射
方法更快,并且在可能的情况下,应该优先选择,在这种情况下,列表理解实际上较慢:
~$python-m timeit-s'import random;l=[[]if random.random()<0.5 else[1]表示uuu在范围内(1000000)]“[x表示在l if x中的x]”
10个循环,每个循环最好3:44.9毫秒
~$python-m timeit-s'导入随机;l=[]if random.random()<0.5 else[1]表示“范围内(1000000)]”过滤器(无,l)
10个循环,每个循环最好3:25.7毫秒
@nelfin这两个测试不是在两个不同的随机列表上运行吗?可能重复