我试图在包含其他文件夹的文件夹中列出所有png文件。这是我的代码。
import os
filelist=os.listdir('images')
for fichier in filelist:
if not(fichier.endswith(".png")):
filelist.remove(fichier)
print(filelist)
问题是,最后一次打印显示某些子文件夹(但不是全部)逃脱了剔除......
['aa.png', 'Nouveau dossier - Copie', 'Nouveau dossier - Copie (3)', 'Nouveau dossier - Copie (5)', 'zz.png']
我做错了什么?
答案 0 :(得分:13)
迭代时不应修改列表。它会导致有趣的事情发生。
最好使用列表理解:
filelist= [file for file in os.listdir('images') if file.endswith('.png')]
答案 1 :(得分:8)
摘要:从不,永远,修改您正在迭代的列表。
相反,迭代副本:
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)
或者,如果您不想制作不必要的副本,请反向迭代(这只有在您可以保证列表中的项目是唯一的时才有效;对于文件系统,这是一个很好的假设):< / p>
for fichier in reversed(filelist):
# do stuff
请注意,您可以使用Python的glob
模块来简化此操作:
import glob
print(glob.glob('images/*.png'))
当您在Python中迭代列表时,Python在实际上迭代列表的索引。您可以看到,实际删除项目时这是一个很大的问题:
l = [1, 2, 2, 3]:
for x in l:
if x%2 == 0:
l.remove(x)
print('x == {}'.format(x))
print('l == {}'.format(l))
您可以根据此处打印的内容判断跳过第二个2,l
的值为[1, 2, 3]
。这是因为,无论何时达到并移除前2,索引都是1
(第二个元素)。在下一次迭代中,索引为2
。此时,l == [1,2,3]
,x == 3
。如果你运行代码,它可能会比这个解释更明显。