擅长:python、mysql、java
<p>小结:<strong>永远,永远,永远</strong>修改正在迭代的列表。</p>
<p>相反,在副本上迭代:</p>
<pre><code>import os
filelist=os.listdir('images')
for fichier in filelist[:]: # filelist[:] makes a copy of filelist.
if not(fichier.endswith(".png")):
filelist.remove(fichier)
print(filelist)
</code></pre>
<p>或者,如果您不想进行不必要的复制,请反向迭代(这只有在您能够保证列表中的项是唯一的时才有效;对于文件系统,这是一个很好的假设):</p>
<pre><code>for fichier in reversed(filelist):
# do stuff
</code></pre>
<p>请注意,您可以使用Python的<code>glob</code>模块来简化:</p>
<pre><code>import glob
print(glob.glob('images/*.png'))
</code></pre>
<h2>为什么</h2>
<p>在Python中遍历列表时,Python实际上是在后台遍历列表的索引。你可以看到这是一个巨大的问题,每当你真正删除的项目:</p>
<pre><code>l = [1, 2, 2, 3]:
for x in l:
if x%2 == 0:
l.remove(x)
print('x == {}'.format(x))
print('l == {}'.format(l))
</code></pre>
<p>从这里打印的内容可以看出跳过了第二个2,并且<code>l</code>的值为<code>[1, 2, 3]</code>。这是因为,只要到达并移除前2个,索引就是<code>1</code>(第二个元素)。在下一次迭代中,索引是<code>2</code>。此时,<code>l == [1,2,3]</code>,所以<code>x == 3</code>。如果运行代码,可能比这个解释更明显。</p>