用于在不断变化的列表上进行迭代的Python习惯用法

用于在不断变化的列表上进行迭代的Python习惯用法,python,for-loop,Python,For Loop,python中有没有更好(更明显/更惯用)的方法来编写 index = 0 while index < len(some_list): do_some_stuff(some_list[index]) # may have many side effects if delete_element(some_list[index]): del some_list[index] else: index += 1 index=0 而索引

python中有没有更好(更明显/更惯用)的方法来编写

index = 0
while index < len(some_list):
    do_some_stuff(some_list[index]) # may have many side effects
    if delete_element(some_list[index]):
        del some_list[index]
    else:
        index += 1
index=0
而索引

或者是字典里的字典?Dict/list理解不是一件事,因为
delete\u element
的结果可能取决于
do\u some\u stuff

您可以将操作分解为两个单独的循环,并对第二部分使用list理解

for value in some_list:
    do_some_stuff(value)

some_list = [value for value in some_list if not delete_element(value)]
另一种解决方案是迭代列表的副本,并使用
enumerate
跟踪索引,而不必手动维护计数器

for index, value in enumerate(some_list[::-1]):
    do_some_stuff(value)
    if delete_element(value):
        del some_list[-index - 1]

您希望向后迭代,这样就不必为删除的元素调整
索引。

如果顺序不重要,您可以向后枚举,这样删除操作就不会弄乱列表中尚未处理的部分

for i, item in enumerate(reversed(somelist), -len(somelist)+1):
    do_some_stuff(item)
    if delete_element(item):
        del somelist[-i]
如果顺序确实重要,则颠倒列表,执行此技巧,然后再次颠倒。那会把他们弄糊涂的

根据情况,您可以使用类似None的标记替换该项。请稍后将其删除,或将此列表用于其他位置。无

for i, item in enumerate(somelist)):
    do_some_stuff(item)
    if delete_element(item):
        somelist[i] = None

somelist = [item for item in somelist if item]

你甚至可以假设
做一些东西
返回
,这样做:

res = [item for item in some_list if not delete_element(do_some_stuff(item))]

毫无意义的方法是使用发电机:

def do_stuff_and_filter_items(items):
    for item in items:
        do_some_stuff(item)
        if not delete_element(item):
            yield item
然后,要获得一个iterable:

items = do_stuff_and_filter_items(items)
或获取列表:

items = list(do_stuff_and_filter_items(items))
或覆盖旧列表:

items[:] = do_stuff_and_filter_items(items)

enumerate
从零开始向上计数,即使在反向迭代器上调用它也是如此。您需要使用
del some\u list[-index-1]
以便删除的索引与项目一起倒计时。您的
enumerate
调用不会生成与反向值匹配的索引(
somelist[-len(somelist)+1]
somelist[0]
)。您可能需要
枚举(反向(somelist),1)
然后是
del somelist[-index]
@Blckknght-您的权利,我想使用abs(I)。enumerate不倒计时,所以技巧是从负数开始,然后让它变为零。但是,正如您所说,使用负索引删除错误的值。-代码中已修复。啊,这确实更好。但是,我会使用
-I
而不是
abs(I)
,因为后者会检查该值的符号,而您不需要它(您总是希望对现有值求反)。@Blckknght-也改变了这一点。每个循环剪切一个甜美的.00000003秒(微笑)。考虑到我未说明的修改列表的要求,这个答案最适合。它还教会了我传递第二个参数进行枚举的好技巧。