Python懒惰的布尔评估出了什么问题?

时间:2013-09-26 05:52:13

标签: python

为什么会这样:

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

......但这不是吗?

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

我很困惑,我在这里错过了什么?

5 个答案:

答案 0 :(得分:3)

评估

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

首先评估 s[i]。对于i = 3,这会引发IndexError

答案 1 :(得分:1)

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

当您执行以下操作时:

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

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

或者,如果你这样检查:

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

当且仅当第一个条件的计算结果为真时,它才会检查第二个条件i < len(s)。在Python中,这些条件按顺序进行评估,重要的是要记住andor从左到右依次检查条件,它们也会短路(如果真值可以从真相中确定)第一个条件的值,第二个条件根本没有评估。)

答案 2 :(得分:0)

因为在第二种情况下,

在访问s [i]

后检查i的索引

因此,即使i = 3,

首先尝试访问s [3],然后检查i&gt; 2。

答案 3 :(得分:0)

下面

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

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

答案 4 :(得分:0)

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