2013-09-26 98 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從左到右依次檢查條件,並且它們也會短路(如果真值可以從第一條件的真值確定,第二條件根本沒有被評估。)