2013-09-26 4 views
0

Почему это работает:Python lazy boolean оценка пошла не так?

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

В 's [i] не в 'aeiou' и i

+1

На самом деле название должно гласить: «Ленькая оценка работает точно, как ожидалось и документирована». – Hyperboreus

ответ

3

Для оценки

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

первыйs[i] оценивается. Для i = 3 это выбрасывает IndexError.

+0

Ах, ладно, это супер ясный ответ, теперь я понимаю! – SanderC

0

, потому что во втором случае,

проверка I, индекса осуществляется после получения доступа с [I]

Таким образом, даже если я = 3,

он будет пытаться доступ s [3 ] первый, а затем проверить, что я> 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):

Если и только тогда, когда первое условие истинно, он будет проверять второе условие i < len(s). В Python эти условия оцениваются по порядку, и важно помнить, что как and, так и or проверяют условия последовательно слева направо, а также короткие замыкания (если значение истины можно определить из значения истины первого условия, второе вообще не оценивается.)

Смежные вопросы