0

Why this works:

s = 'xyz'
i = 0     
while i < len(s) and s[i] not in 'aeiou':
        print(s[i])
        i += 1
x
y
z

... but this does not?

s = 'xyz'
i = 0 
while s[i] not in 'aeiou' and i < len(s):
    print(s[i])
    i += 1
x
y
z
Traceback (most recent call last):
  File "<pyshell#135>", line 1, in <module>
    while s[i] not in 'aeiou' and i <= len(s):
IndexError: string index out of range

I'm confused, what am I missing here?

4

5 回答 5

3

评估

s[i] not in 'aeiou' and i < len(s)

首先 s[i]是评估。为此i = 3抛出一个IndexError.

于 2013-09-26T05:54:36.553 回答
1

and是一个二元布尔运算符,它首先检查其左操作数的条件值,然后当且仅当左操作数的计算结果为 True 时检查其右操作数的条件值。您的第二个代码超出了界限,因为您没有首先检查是否i在您的字符串长度范围内s

当您执行以下操作时:

while i < len(s) and s[i] not in 'aeiou':

运算符将and短路,并且如果自身超出字符串范围,则不会检查是否s[i]不在 'aeiou'中。i因此,您可以安全地避免对字符串的越界数组访问!如果您翻转条件的顺序,您将检查是否s[i]在 'aeiou' 中,而无需先检查 'i' 是否在范围内。

或者,如果您像这样检查它:

while s[i] not in 'aeiou' and i < len(s):

当且仅当第一个条件的计算结果为真时,它才会检查第二个条件i < len(s)。在 Python 中,这些条件是按顺序计算的,重要的是要记住从左到右依次检查条件和短路(如果真值可以从第一个条件的真值确定,则第二个and不是or完全评估。)

于 2013-09-26T05:56:24.247 回答
0

因为在第二种情况下,

访问 s[i] 后检查 i 的索引

因此,即使 i = 3,

它将首先尝试访问 s[3],然后检查 i > 2。

于 2013-09-26T05:54:53.467 回答
0

这里

while s[i] not in 'aeiou' and i < len(s):

您在检查是否在范围内s[i] 之前访问。i

于 2013-09-26T05:54:53.640 回答
0

按顺序评估条件。当您颠倒条件的顺序时,您会导致执行不同的代码。在这种特定情况下,当您访问字符串中不存在的索引时会导致异常。这在其他结果中永远不会发生,因为遇到第一个 False 时条件“短路”。

于 2013-09-26T05:54:53.680 回答