我有这样一段代码:
numbers = list(range(1, 50))
for i in numbers:
if i < 20:
numbers.remove(i)
print(numbers)
但是,我得到的结果是:[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49]
当然,我希望低于20的数字不会出现在结果中。看来我在移除的时候出了点问题。
9条答案
按热度按时间bzzcjhmw1#
在迭代列表的同时也在修改它。这意味着第一次通过循环
i == 1
,所以1从列表中删除。然后for
循环转到列表中的第二项,它不是2,而是3!然后从列表中删除,然后for
循环继续到列表中的第三项,现在是5。以此类推。也许这样更容易形象化,用一个^指向i
的值:这是列表的初始状态;然后删除1,循环转到列表中的第二项:
等等。
在遍历列表时,没有好的方法来改变列表的长度。你能做的最好的事情是这样的:
或者这个,用于就地改变(括号中的东西是一个生成器表达式,它在切片赋值之前被隐式转换为元组):
如果你想在删除n之前对它执行一个操作,你可以尝试的一个技巧是:
1zmg4dgp2#
从列表的末尾开始并向后:
结果:
mwecs4sa3#
@senderle的答案是要走的路!
话虽如此,为了进一步说明你的问题,如果你想一想,你总是想删除索引0二十次:
所以你实际上可以这样做:
希望能帮上忙。
下面的是不坏的做法AFAIK。
编辑(更多):
也会做这项工作。
第2章(我很无聊):
dbf7pr2w4#
所以我找到了一个解决办法,但它真的很笨拙…
首先,你做一个索引数组,在其中列出所有你想删除的索引,如下所示
之后,你要从numbers列表中删除所有条目,索引保存在index_arr中。你会遇到的问题和以前一样。因此,在从数字arr中删除一个数字后,必须从index_arr中的每个索引中减去1,如下所示:
它会起作用,但我猜这不是我们预期的方法
au9on6nz5#
作为@Senderle的回答的附加信息,只是为了记录,我认为当python在“Sequence type”上看到
for
时,可视化场景背后的逻辑是有帮助的。假设我们有:
它实际上将是:
就是这样,当我们在Sequence类型或Iterables上使用
for
时,for
有一个try-catch机制(虽然有点不同-调用next()
和StopIteration
异常)。index
的独立变量,因此无论列表发生什么(删除或添加),python都会递增该变量并使用“this variable”调用__getitem__()
方法并要求item。gzszwxb46#
基于@eyquem的答案并将其简化...
问题是,当你迭代的时候,元素被从你下面拉出来,当你前进到下一个数字的时候,跳过数字。
如果你从末尾开始并向后移动,在移动中删除项目将不会有什么影响,因为当它移动到“下一个”项目(实际上是前一个项目)时,删除不会影响列表的前半部分。
只需将
reversed()
添加到迭代器即可解决问题。注解是一种很好的形式,可以防止将来的开发人员“整理”您的代码并神秘地破坏它。xqnpmsa87#
您也可以使用continue忽略小于20的值
rjzwgtxy8#
从Python 3.3开始,你可以使用list
copy()
方法作为迭代器:iyfjxgzm9#
您可以使用list()为
numbers
创建一个不同的复制numbers
,如下所示: