从列表中删除项目 - 在迭代期间 - 这个习语有什么问题? [英] Removing Item From List - during iteration - what's wrong with this idiom?

查看:18
本文介绍了从列表中删除项目 - 在迭代期间 - 这个习语有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为一个实验,我这样做了:

As an experiment, I did this:

letters=['a','b','c','d','e','f','g','h','i','j','k','l']
for i in letters:
    letters.remove(i)
print letters

最后一次打印显示并非所有项目都已删除?(其他都是).

The last print shows that not all items were removed ? (every other was).

IDLE 2.6.2      
>>> ================================ RESTART ================================
>>> 
['b', 'd', 'f', 'h', 'j', 'l']
>>> 

这是什么解释?如何重写以删除每个项目?

What's the explanation for this ? How it could this be re-written to remove every item ?

推荐答案

有些答案解释了为什么会发生这种情况,有些解释了您应该做什么.我会无耻地拼凑起来.

Some answers explain why this happens and some explain what you should've done. I'll shamelessly put the pieces together.

因为 Python 语言旨在以不同方式处理此用例.文档说得很清楚:

Because the Python language is designed to handle this use case differently. The documentation makes it clear:

修改循环中被迭代的序列是不安全的(这只会发生在可变序列类型,例如列表).如果您需要修改正在迭代的列表(例如,复制选定的项目),您必须迭代一个副本.

It is not safe to modify the sequence being iterated over in the loop (this can only happen for mutable sequence types, such as lists). If you need to modify the list you are iterating over (for example, to duplicate selected items) you must iterate over a copy.

强调我的.有关更多信息,请参阅链接页面 - 文档受版权保护,并保留所有权利.

Emphasis mine. See the linked page for more -- the documentation is copyrighted and all rights are reserved.

你很容易理解为什么你得到了你所得到的,但基本上未定义行为可以轻松更改,从构建到构建都没有警告.只是不要这样做.

You could easily understand why you got what you got, but it's basically undefined behavior that can easily change with no warning from build to build. Just don't do it.

这就像 想知道为什么 i += i++ + ++i 在你的语言的编译器的特定构建上对你的架构做任何事情 - 包括但不限于 破坏您的计算机让恶魔飞出你的鼻子 :)

It's like wondering why i += i++ + ++i does whatever the hell it is it that line does on your architecture on your specific build of your compiler for your language -- including but not limited to trashing your computer and making demons fly out of your nose :)

  • del letter[:](如果你需要改变对这个对象的所有引用)
  • letters[:] = [](如果你需要改变对这个对象的所有引用)
  • letters = [](如果你只是想处理一个新对象)
  • del letters[:] (if you need to change all references to this object)
  • letters[:] = [] (if you need to change all references to this object)
  • letters = [] (if you just want to work with a new object)

也许您只想根据条件删除一些项目?在这种情况下,您应该迭代列表的副本.制作副本的最简单方法是使用 [:] 语法制作一个包含整个列表的切片,如下所示:

Maybe you just want to remove some items based on a condition? In that case, you should iterate over a copy of the list. The easiest way to make a copy is to make a slice containing the whole list with the [:] syntax, like so:

#remove unsafe commands
commands = ["ls", "cd", "rm -rf /"]
for cmd in commands[:]:
  if "rm " in cmd:
    commands.remove(cmd)

如果您的支票不是特别复杂,您可以(并且可能应该)进行过滤:

If your check is not particularly complicated, you can (and probably should) filter instead:

commands = [cmd for cmd in commands if not is_malicious(cmd)]

这篇关于从列表中删除项目 - 在迭代期间 - 这个习语有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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