mon*_*nny 24 python loops list
作为一个实验,我这样做了:
letters=['a','b','c','d','e','f','g','h','i','j','k','l']
for i in letters:
letters.remove(i)
print letters
Run Code Online (Sandbox Code Playgroud)
最后一次打印显示并非所有项目都被删除了?(每隔一个人).
IDLE 2.6.2
>>> ================================ RESTART ================================
>>>
['b', 'd', 'f', 'h', 'j', 'l']
>>>
Run Code Online (Sandbox Code Playgroud)
对此有何解释?如何重新编写以删除每个项目?
bad*_*adp 38
一些答案解释了为什么会发生这种情况,并解释一些你应该做的事情.我会无耻地把碎片放在一起.
因为Python语言旨在以不同方式处理此用例.文档清楚地表明:
修改循环中迭代的序列是不安全的(这只能发生在可变序列类型中,例如列表).如果您需要修改正在迭代的列表(例如,复制所选项目),则必须迭代副本.
强调我的.有关详细信息,请参阅链接页面 - 文档受版权保护,并保留所有权利.
你可以很容易地理解为什么你得到了你得到的东西,但它基本上是未定义的行为,可以很容易地改变而不会从构建到构建发出警告.只是不要这样做.
这就像想知道为什么i += i++ + ++i你的架构在你的语言编译器的特定构建上对你的架构做了什么呢 - 包括但不限于摧毁你的计算机并让恶魔飞出你的鼻子 :)
del letters[:] (如果需要更改对该对象的所有引用)letters[:] = [] (如果需要更改对该对象的所有引用)letters = [] (如果你只想使用一个新对象)也许你只是想根据条件删除一些项目?在这种情况下,您应该迭代列表的副本.制作副本的最简单方法是使用[:]语法创建包含整个列表的切片,如下所示:
#remove unsafe commands
commands = ["ls", "cd", "rm -rf /"]
for cmd in commands[:]:
if "rm " in cmd:
commands.remove(cmd)
Run Code Online (Sandbox Code Playgroud)
如果您的支票不是特别复杂,您可以(也可能应该)过滤:
commands = [cmd for cmd in commands if not is_malicious(cmd)]
Run Code Online (Sandbox Code Playgroud)
你不能迭代列表并同时改变它,而是遍历切片:
letters=['a','b','c','d','e','f','g','h','i','j','k','l']
for i in letters[:]: # note the [:] creates a slice
letters.remove(i)
print letters
Run Code Online (Sandbox Code Playgroud)
也就是说,对于像这样的简单操作,你应该简单地使用:
letters = []
Run Code Online (Sandbox Code Playgroud)
小智 7
您无法修改正在迭代的列表,否则您将获得这种奇怪的结果类型.为此,您必须遍历列表的副本:
for i in letters[:]:
letters.remove(i)
Run Code Online (Sandbox Code Playgroud)
你想要做的是:
letters[:] = []
Run Code Online (Sandbox Code Playgroud)
要么
del letters[:]
Run Code Online (Sandbox Code Playgroud)
这将保留原始对象letters指向.其他选项,如,letters = []会创建一个新对象并指向letters它:旧对象通常会在一段时间后被垃圾收集.
并非所有值都被删除的原因是您在迭代时更改列表.
ETA:如果要从列表中过滤值,可以使用如下列表推导:
>>> letters=['a','b','c','d','e','f','g','h','i','j','k','l']
>>> [l for l in letters if ord(l) % 2]
['a', 'c', 'e', 'g', 'i', 'k']
Run Code Online (Sandbox Code Playgroud)
它会删除第一次出现,然后检查序列中的下一个数字.由于序列已经改变,它需要下一个奇数,依此类推......