我希望有人可以向我解释这种行为以及发生了什么。
如果我运行以下代码:
phrase = "Don't Panic!"
phraseList = list(phrase)
print(phrase)
print(phraseList)
ontap = ['o', 'n', 't', 'a', 'p']
for letter in phraseList:
print("Letter ", letter)
#if letter not in ontap:
# phraseList.remove(letter)
print(phraseList)
我得到以下预期输出:
Don't Panic!
['D', 'o', 'n', "'", 't', ' ', 'P', 'a', 'n', 'i', 'c', '!']
Letter D
Letter o
Letter n
Letter '
Letter t
Letter
Letter P
Letter a
Letter n
Letter i
Letter c
Letter !
['D', 'o', 'n', "'", 't', ' ', 'P', 'a', 'n', 'i', 'c', '!']
但是,如果删除评论,我会收到这种意外行为:
Don't Panic!
['D', 'o', 'n', "'", 't', ' ', 'P', 'a', 'n', 'i', 'c', '!']
Letter D
Letter n
Letter '
Letter
Letter a
Letter n
Letter i
Letter !
['o', 'n', 't', 'P', 'a', 'n', 'c']
所以我的问题是,在循环中我希望PRINT
首先在列表之前执行。 remove
函数运行但似乎没有那样工作。为什么?它似乎是像字母C一样在字体中跳过字母。
另外,为什么比较似乎忽略了字母C,当它明显不在ontap
变量中时。
我可能遗漏了一些非常明显的东西。它是否与调整列表大小并同时在其上运行循环有关?
感谢您的任何见解。
答案 0 :(得分:0)
正如对该问题的评论所证实的那样,问题确实是在迭代它时修改phraseList
。更详细一点,发生了什么:当你进入for循环时,会创建一个迭代器来迭代phraseList
。在第一次迭代中,迭代器提供phraseList[0]
,即D
。这不在ontap
列表中,因此我们执行phraseList.remove('D')
。在下一次迭代中,phraseList
现在是['o', 'n', "'", 't', ...]
,但迭代器不知道它已被更改 - 它只知道它现在需要提供phraseList[1]
,现在是n
}。这就是第二次迭代打印n
而不是o
的原因。永远不会从c
移除phraseList
,因为它出现的唯一位置是在第一次出现i
之后。从i
移除phraseList
后,在下一个循环中,会跳过c
。 (同样,P
未被移除,因为它位于第一个<space>
实例之后。)
修复循环的最简单方法是迭代phraseList
的副本:
for letter in list(phraseList):
print("Letter ", letter)
if letter not in ontap:
phraseList.remove(letter)
这样更改原始phraseList
不会影响迭代。通过列表理解,您也可以更简洁(并且在我看来,更清晰)。以下内容完全实现了上面的for循环:
phraseList = [letter for letter in phraseList if letter in ontap]