使用python遍历列表时修改列表 [英] Modifying a list while iterating over it with python

查看:188
本文介绍了使用python遍历列表时修改列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我想修改原始列表时,我知道要遍历列表的副本.但是,我唯一收到的关于在迭代列表时修改列表出了什么问题的解释是它可能导致意外的结果".

I know to iterate over a copy of my list when I want to modify the original. However, the only explanation I've ever received on what's wrong with modifying a list while iterating over it is that "it can lead to unexpected results."

请考虑以下内容:

lst = ['a', 'b', 'c', 'd', 'e']
for x in lst:
    lst.remove(x)
print(lst)

这是我的尝试,试图解释在迭代列表时修改列表时实际发生的情况.请注意,第2行等效于for i in range(len(lst)):,并且每次迭代len(lst)都会减少1.

Here is my attempt at explaining what actually happens when one modifies a list while iterating over it. Note that line2 is equivalent to for i in range(len(lst)):, and that len(lst) decreases by 1 with every iteration.

len(lst)从5开始.

i = 0时,我们删除了lst[i] = 'a',因此lst = ['b', 'c', 'd', 'e']. len(lst)减少到4.

When i = 0, we have lst[i] = 'a' being removed, so lst = ['b', 'c', 'd', 'e']. len(lst) decreases to 4.

i = 1时,我们删除了lst[i] = 'c',因此lst = ['b', 'd', 'e'] len(lst)减少到3.

When i = 1, we have lst[i] = 'c' being removed, so lst = ['b', 'd', 'e'] len(lst) decreases to 3.

i = 2时,我们删除了lst[i] = 'e',因此lst = ['b', 'd']. len(lst)减少至2.

When i = 2, we have lst[i] = 'e' being removed, so lst = ['b', 'd']. len(lst) decreases to 2.

这是我认为将引发IndexError的地方,因为i = 2不在range(2)中.但是,该程序仅输出['b', 'd'].是因为i已赶上" len(lst)吗?另外,我的推理到目前为止是否正确?

This is where I thought an IndexError would be raised, since i = 2 is not in range(2). However, the program simply outputs ['b', 'd']. Is it because i has "caught up" with len(lst)? Also, is my reasoning sound so far?

推荐答案

C实现位于listiter_next函数中/listobject.c"rel =" nofollow noreferrer> listobject.c 和相关的行是

The C implementation is in the listiter_next function in listobject.c and the pertinent lines are

if (it->it_index < PyList_GET_SIZE(seq)) {
    item = PyList_GET_ITEM(seq, it->it_index);
    ++it->it_index;
    Py_INCREF(item);
    return item;
}

it->it_seq = NULL;
Py_DECREF(seq);
return NULL;

如果迭代器的对象仍在范围内(it->it_index < PyList_GET_SIZE(seq)),则迭代器返回该对象,否则返回NONE.不管您是减少一百万还是一百万,这都不是错误.

The iterator returns an object if its still in range (it->it_index < PyList_GET_SIZE(seq)) and returns NONE otherwise. It doesn't matter if you are off by 1 or a million, its not an error.

以这种方式执行操作的一般原因是,迭代器和可迭代对象可以在多个位置使用(考虑在for循环内读取的文件对象).外循环不应该因为IndexError而崩溃,因为它用尽了所有要做的事情.更改您要迭代的对象不是非法的或天生的愚蠢",只是您需要知道操作的后果.

The general reason for doing things this way is that iterators and iterables can be consumed in multiple places (consider a file object that is read inside a for loop). An outer loop shouldn't crash with an IndexError just because its run out of things to do. Its not illegal or inherently "stupid" to change an object you are iterating, its just that you need to know the consequences of your actions.

这篇关于使用python遍历列表时修改列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆