<p>引用<a href="https://docs.python.org/3/reference/compound_stmts.html#the-for-statement" rel="nofollow noreferrer">from the docs</a>:</p>
<blockquote>
<p><strong>Note</strong>: There is a subtlety when the sequence is being modified by the
loop (this can only occur for mutable sequences, i.e. lists). An
internal counter is used to keep track of which item is used next, and
this is incremented on each iteration. When this counter has reached
the length of the sequence the loop terminates. This means that if the
suite deletes the current (or a previous) item from the sequence, the
next item will be skipped (since it gets the index of the current item
which has already been treated). Likewise, if the suite inserts an
item in the sequence before the current item, the current item will be
treated again the next time through the loop. This can lead to nasty
bugs that can be avoided by making a temporary copy using a slice of
the whole sequence, e.g.,</p>
</blockquote>
<pre><code>for x in a[:]:
if x < 0: a.remove(x)
</code></pre>
<hr/>
<p>使用<code>[:]</code>遍历列表的浅副本。您在迭代列表时正在修改它,这将导致某些字母丢失。</p>
<p>循环<code>for</code>跟踪索引,因此当您删除索引<code>i</code>处的项时,第<code>i+1</code>位置处的下一项将移到当前索引(<code>i</code>),因此在下一次迭代中,您将实际选择第<code>i+2</code>项。</p>
<p>举个简单的例子:</p>
<pre><code>>>> text = "whoops"
>>> textlist = list(text)
>>> textlist
['w', 'h', 'o', 'o', 'p', 's']
for char in textlist:
if char.lower() in 'aeiou':
textlist.remove(char)
</code></pre>
<p><strong>迭代1:索引=0。</strong></p>
<p><code>char = 'W'</code>在索引0处。因为它不满足那个条件,所以你什么也不做。</p>
<p><strong>迭代2:索引=1。</strong></p>
<p><code>char = 'h'</code>在索引1处。这里没什么可做的了。</p>
<p><strong>迭代3:索引=2。</strong></p>
<p><code>char = 'o'</code>在索引2中。由于此项满足条件,因此它将从列表中移除,并且其右侧的所有项将向左移动一个位置以填补空白。</p>
<p>现在<code>textlist</code>变成:</p>
<pre><code> 0 1 2 3 4
`['w', 'h', 'o', 'p', 's']`
</code></pre>
<p>如您所见,另一个<code>'o'</code>移动到了索引2,即当前索引,因此在下一次迭代中将跳过它。所以,这就是为什么有些项目在迭代中被跳过的原因。无论何时删除项,都将跳过迭代中的下一项。</p>
<p><strong>迭代4:索引=3。</strong></p>
<p><code>char = 'p'</code>在索引3处。</p>
<p>。。。。</p>
<hr/>
<h2>修复:</h2>
<p>迭代列表的浅层副本以解决此问题:</p>
<pre><code>for char in textlist[:]: #note the [:]
if char.lower() in 'aeiou':
textlist.remove(char)
</code></pre>
<hr/>
<h2>其他替代方案:</h2>
<p><strong>列表理解:</strong></p>
<p>使用<code>str.join</code>和<code>list comprehension</code>的一行:</p>
<pre><code>vowels = 'aeiou'
text = "Hey look Words!"
return "".join([char for char in text if char.lower() not in vowels])
</code></pre>
<p><strong>正则表达式:</strong></p>
<pre><code>>>> import re
>>> text = "Hey look Words!"
>>> re.sub('[aeiou]', '', text, flags=re.I)
'Hy lk Wrds!'
</code></pre>