2013-09-26 55 views
0

为什么这个工程: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 

我很困惑,我缺少什么吗?

+0

在'我[i]不在'aeiou'和我 2013-09-26 05:54:52

+1

实际上标题应该是“懒惰的评估工作,如预期和记录一样。 – Hyperboreus

回答

3

为了评价

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

第一s[i]进行评价。对于i = 3,这会抛出一个IndexError

+0

嗯,好吧,这是超级明确的答案,现在我明白了! – SanderC

0

因为在第二种情况下,我的指数的

检查在访问S [I]

因此之后进行,甚至若i = 3,

它将尝试访问S [3 ],然后再检查I> 2

0

这里

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

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

0

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

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):

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