Python 中 for..in 循环的意外输出

Unexpected output of for.. in loop in Python

我想 运行 一个 for 循环来检查字符串中的每个字母,如果 wanted 列表包含该字母,那么我希望该字母保留,如果 wanted 包含不包含字母,然后我想删除它。

phrase = "Don't panic"
pList = list(phrase)
print(pList)
wanted = ["o","n","t","a","p"]
for anything in pList:
    print("Now checking", anything)
    if anything not in wanted:
        print("Removed",anything) 
        pList.remove(anything)
    elif anything in wanted:
        print("Didn't remove", anything)

print(pList)

下面的代码returns这样输出-

['D', 'o', 'n', "'", 't', ' ', 'p', 'a', 'n', 'i', 'c']                                                   

Now checking D                                                                                       
Removed D                                                                                                                                                                                           
Now checking n                                                                                          
Didn't remove n                                                                                         
Now checking '                                                                                           
Removed '                                                                                                                                                                                               
Now checking                                                                                              
Removed                                                                                                                                                                                                 
Now checking a                                                                                           
Didn't remove a                                                                                         
Now checking n                                                                                           
Didn't remove n                                                                                           
Now checking i                                                                                          
Removed i                                                                                                                                                                                       
['o', 'n', 't', 'p', 'a', 'n', 'c']   

代码没有删除最后一个字母(即 "c"),字母 "o"、"t"、"p" 和 "c" 没有显示 Now checking 输出。

我尝试删除一些行,只是 运行 -

phrase = "Don't panic"
pList = list(phrase)
print(pList)
wanted = ["o","n","t","a","p"]
for anything in pList:
    print("Now checking", anything)

这次输出有意义 -

Now checking D                                                                                            
Now checking o                                                                                            
Now checking n                                                                                            
Now checking '                                                                                            
Now checking t                                                                                            
Now checking                                                                                              
Now checking p                                                                                            
Now checking a                                                                                            
Now checking n                                                                                            
Now checking i                                                                                            
Now checking c 

那么,当完整代码为 运行 时,为什么不会发生这种情况?

您在迭代列表时正在编辑列表。因此,大小会在中途发生变化,最终会出现奇怪的行为。您可以改为创建一个新列表来保存过滤后的字符。

phrase = "Don't panic"
pList = list(phrase)
new_plist = []
wanted = ["o","n","t","a","p"]
for i, anything in enumerate(pList):
    print("Now checking", anything)
    if anything in wanted:
        print("Didn't remove", anything)
        new_plist.append(anything)
    else:
        print("Removed", anything)

print(new_plist)

使用列表理解的更简单方法是

pList = ''.join([i for i in pList if i not in wanted])

其他答案和评论 100% 正确 - 切勿在遍历列表时修改它!可能有助于解决这类问题的是逆向思考问题:不是从列表中 删除 ,而是反转条件和 添加 到一个新列表。通过这种方式,它基于输入而不是改变输入来构建新的输出 = 更少的副作用、更清晰的代码、函数式编程原则等。@coldspeed 的列表理解是一种优雅的解决方案。

对原始代码进行最少更改的替代解决方案:

phrase = "Don't panic"
pList = list(phrase)
print(pList)
wanted = ["o","n","t","a","p"]
finalList = []
for anything in pList:
    print("Now checking", anything)
    if anything in wanted:
        finalList.append(anything)
        print("Didn't remove", anything)
    else:
        print("Removed",anything)

print(finalList)

现在 pList 没有被修改,新的 finalList 包含所需的结果。 (编辑:意识到@coldspeed 的代码现在几乎与此完全相同——我最初提交时不是这样。)