您正在迭代一个列表并同时从中删除元素。
首先,我需要确保您清楚地了解char 在for char in textlist: ... 中的作用。以我们到达字母“l”的情况为例。情况不是这样的:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char
char 与列表中字母“l”的位置之间没有链接。如果修改char,列表将不会被修改。情况更像是这样的:
['H', 'e', 'y', ' ', 'l', 'o', 'o', 'k', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
char = 'l'
请注意,我保留了 ^ 符号。这是管理for char in textlist: ... 循环的代码用来跟踪其在循环中的位置的隐藏指针。每次进入循环体,指针前进,指针引用的字母被复制到char中。
当您连续有两个元音时,就会出现问题。我会告诉你从你到达“l”的那一点会发生什么。请注意,我还将“look”一词更改为“leap”,以便更清楚地了解发生了什么:
将指针前进到下一个字符 ('l') 并复制到 char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'l'
char ('l') 不是元音,所以什么都不做
将指针前进到下一个字符 ('e') 并复制到 char
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'e'
char ('e') 是元音,所以删除char ('e') 的第一个匹配项
['H', 'e', 'y', ' ', 'l', 'e', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', <- 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
^
将指针前进到下一个字符 ('p') 并复制到 char
['H', 'e', 'y', ' ', 'l', 'a', 'p', ' ', 'W', 'o', 'r', 'd', 's', '!']
-> ^
char = 'p'
当您删除“e”时,“e”之后的所有字符都向左移动了一位,所以就好像remove 已经推进了指针。结果是您跳过了“a”。
一般来说,您应该避免在迭代列表时修改列表。最好从头开始构建一个新列表,Python 的列表推导式是执行此操作的完美工具。例如
print ''.join([char for char in "Hey look Words" if char.lower() not in "aeiou"])
但如果你还没有学过推导式,最好的方法可能是:
text = "Hey look Words!"
def anti_vowel(text):
textlist = list(text)
new_textlist = []
for char in textlist:
if char.lower() not in 'aeiou':
new_textlist.append(char)
return "".join(new_textlist)
print anti_vowel(text)