Python-从列表中删除项-在迭代过程中-这个习惯用法有什么问题?

发布于 2021-02-02 23:14:03

作为实验,我这样做:

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

最后打印显示不是所有项目都被删除了吗?(其他所有人)。

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

这有什么解释?如何将其重写以删除所有项目?

关注者
0
被浏览
78
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    这是什么原因呢?

    因为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)
    

    如果你的检查不是特别复杂,则可以(可能应该)过滤:

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


知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看