<p>您正在修改正在迭代的列表,这必然会导致一些不直观的行为。相反,复制列表,这样就不会从迭代的内容中删除元素。</p>
<pre><code>for char in textlist[:]: #shallow copy of the list
# etc
</code></pre>
<hr/>
<p>为了澄清你看到的行为,看看这个。把<code>print char, textlist</code>放在(原始)循环的开头。您可能会期望,这会在列表旁边垂直打印出字符串,但实际得到的是:</p>
<pre><code>H ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
e ['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] # !
l ['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
o ['H', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
k ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!'] # Problem!!
['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
W ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
o ['H', 'y', ' ', 'l', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
d ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
s ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
! ['H', 'y', ' ', 'l', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
Hy lk Words!
</code></pre>
<p>怎么了?Python中漂亮的<code>for x in y</code>循环实际上只是语法上的糖:它仍然按索引访问列表元素。因此,当您在列表上迭代时从列表中删除元素时,就开始跳过值(如上图所示)。因此,在<code>"look"</code>中永远看不到第二个<code>o</code>;您跳过它是因为当您删除前一个元素时,索引已经“超过”了它。然后,当您到达<code>"Words"</code>中的<code>o</code>时,您将删除<code>'o'</code>的第一个匹配项,这是您之前跳过的一个匹配项。</p>
<hr/>
<p>正如其他人所提到的,列表理解可能是一种更好(更干净、更清晰)的方法。利用Python字符串是可iterable的这一事实:</p>
<pre><code>def remove_vowels(text): # function names should start with verbs! :)
return ''.join(ch for ch in text if ch.lower() not in 'aeiou')
</code></pre>