迭代时更改列表的最佳方法

Pat*_*ick 10 python loops dynamic

我在python脚本(v2.6)中有几个实例,我需要在其中修改列表.我需要从列表中弹出值以响应用户的交互式输入,并且想知道最干净的方法.目前我有一个非常脏的解决方案:a)将列表中的项目设置为我要删除为False并使用过滤器或列表推导删除它们或b)在循环中生成一个全新的列表,这似乎是不必要的将变量添加到命名空间并占用内存.

这个问题的一个例子如下:

for i, folder in enumerate(to_run_folders):
    if get_size(folder) < byte_threshold:
        ans = raw_input(('The folder {0}/ is less than {1}MB.' + \
                    ' Would you like to exclude it from' + \
                    ' compression? ').format(folder, megabyte_threshold))
        if 'y' in ans.strip().lower():
            to_run_folders.pop(i)
Run Code Online (Sandbox Code Playgroud)

我想查看列表中的每个文件夹.如果当前文件夹小于特定大小,我想询问用户是否要将其排除.如果是,请从列表中弹出文件夹.

这个例程的问题是,如果我遍历列表,我会得到意外的行为并提前终止.如果我通过切片迭代副本,pop不会拉出正确的值,因为索引被移动并且问题在弹出更多项时会复合.我还需要在我的脚本的其他区域中进行此类动态列表调整.这种功能有什么干净的方法吗?

nin*_*cko 9

您可以向后循环列表,或使用视图对象.

有关如何向后循环列表,请参阅/sf/answers/12674371/.基本上使用reversed(yourList)(这会产生一个向后访问的视图对象).

如果你需要索引,你可以这样做reversed(enumerate(yourList)),但这会在内存中有效地创建一个临时列表,因为它enumerate需要在启动之前运行reversed.你需要做索引操作,或者这样做:

for i in xrange(len(yourList)-1, -1, -1):
    item = yourList[i]
    ...
Run Code Online (Sandbox Code Playgroud)

甚至更干净:reversed知道range,所以你可以在python3中执行此操作,或者在python2中执行此操作xrange:

for i in reversed(range(len(yourList))):  
    item = yourList[i]
    ...
Run Code Online (Sandbox Code Playgroud)

(证明:你可以这样做next(reversed(range(10**10))),但如果使用python2,这会使你的计算机崩溃)