Например, если у меня есть следующий оператор:
if( foo1 or foo2)
...
...
Если foo1 истинно, будет ли python проверять состояние foo2?
Например, если у меня есть следующий оператор:
if( foo1 or foo2)
...
...
Если foo1 истинно, будет ли python проверять состояние foo2?
Да, Python лениво оценивает логические условия.
Выражение x и y сначала оценивает x; если x является ложным, его значение равно вернулся; в противном случае y вычисляется, и полученное значение равно вернулся.
Выражение x или y сначала оценивает x; если x истинно, его значение равно вернулся; в противном случае y вычисляется, и полученное значение равно вернулся.
Леность Python может быть подтверждена следующим кодом:
def foo():
print('foo')
return False
def bar():
print('bar')
return False
foo() and bar() #Only 'foo' is printed
С другой стороны,
foo() or bar()
приведет к печати как "foo", так и "bar".
and
or
- ленивый
&
|
не является ленивым
Это не технически ленивая оценка, это короткое замыкание булевых выражений.
Ленивая оценка имеет несколько иную коннотацию. Например, истинная ленивая оценка, вероятно, позволит этому
def foo(arg) :
print "Couldn't care less"
foo([][0])
Но Python этого не делает.
Python также хорош тем, что он "эхо" содержит логические аргументы. Например, an или condition возвращает либо первый аргумент "правдивый", либо последний аргумент (если все аргументы "ложны" ). An и условие обратное.
Итак, "аргумент эха" booleans означает
2 и [] и 1
имеет значение [] и
[] или 1 или 2
оценивается в 1
Да, Python оценивает лениво, поэтому foo2
не будет проверяться.
Я использую это все время для захвата предметов из словарных объектов, если я не знаю, существует ли ключ:
if 'key' in mydict and mydict['key'] == 'heyyo!':
do_stuff()
См. ответ @unutbu для более полного объяснения.
Это действительно часть or
, которая коротко замкнута:
>>> 1 or 1/0 #also 0 and 1/0
1
>>> 0 or 1/0 #also 1 and 1/0
Traceback (most recent call last):
File "<pyshell#1240>", line 1, in <module>
0 or 1/0
ZeroDivisionError: integer division or modulo by zero
Коротким демо было бы сравнение разницы во времени между
all(xrange(1,1000000000))
и
any(xrange(1,1000000000))
Все() должны проверять каждое значение, в то время как any() может отказаться от первого True. Таким образом, xrange, будучи генератором, также отказывается от генерирующих вещей, как только выполняется оценщик. По этой причине все будет потреблять большие объемы оперативной памяти и получать возраст, в то время как любой из них будет использовать всего несколько байтов и мгновенно вернуться.