В Python, если Вы пишете что-то как
foo==bar and spam or eggs
Python, кажется, возвращает спам, если булев оператор верен и яйца иначе. Кто-то мог объяснить это поведение? Почему выражение не оценивает как одна длинная булевская переменная?
Править: А именно, я пытаюсь выяснить механизм, почему 'спам' или 'яйца' возвращаются как результат выражения.
Операторы и
и или
закорачивают, что означает, что если результат выражения может быть выведен из оценки только первого операнда, второй не оценивается.Например, если у вас есть выражение a или b
и a
оценивается как истинное, тогда не имеет значения, что такое b
, результат выражения истинен поэтому b
не оценивается. На самом деле они работают следующим образом:
a и b
: Если a ложно, b не оценивается и возвращается a, в противном случае возвращается b. a или b
: Если a истинно, b не оценивается и возвращается a, в противном случае возвращается b. Ложь и истина относятся к значениям, которые оцениваются как ложь или истина в логическом контексте.
Однако эта и / или идиома были полезны в те времена, когда не было лучшей альтернативы, но теперь есть лучший способ:
spam if foo==bar else eggs
Проблема с и / или идиомой (кроме того, что она сбивает с толку новичков) заключается в том, что он дает неправильный результат, если условие истинно, но спам оценивается как ложное значение (например, пустая строка). По этой причине вам следует избегать этого.
Вот как работают булевы операторы в Python.
Из документации (последний абзац объясняет, почему операторы работают так, как они работают):
В контексте булевых операций, а также когда выражения используются выражений потока управления, следующие значения интерпретируются как false:
False
,None
, числовой ноль всех типов, а также пустые строки и контейнеры (включая строки, кортежи, списки, словари, множества и фростенсеты). Все остальные значения интерпретируются как true. (См.__nonzero__()
специальный метод для изменения этого.)Оператор
not
даетTrue
, если его если его аргумент ложен,False
в противном случае.Выражение
x и y
сначала оценивается так.x
; еслиx
ложно, его значение возвращается; в противном случае оцениваетсяy
и возвращается полученное значение.Выражение
x или y
сначала оценивает.x
; еслиx
истинно, его значение возвращается; в противном случае оценивается y и возвращается результирующее значение.(Обратите внимание, что ни
и
, ниили
не ограничивают значение и тип, которые они возвращают, доFalse
иTrue
, а скорее возвращают последний оцененный аргумент. Это иногда полезно, например, еслиs
представляет собой строка, которая должна быть заменена на значением по умолчанию, если она пуста, то выражениеs или 'foo'
дает нужное значение. Посколькуnot
должно придумать значение в любом случае, оно не беспокоится о том, чтобы вернуть значение того же типа, что и его аргумент, поэтому, например,not 'foo'
возвращаетFalse
, not''
.)
Причина в том, что Python вычисляет логическое выражение, используя фактические значения задействованных переменных, вместо того, чтобы ограничивать их значениями True
и False
. Следующие значения считаются ложными:
Нет
Ложь
''
, ()
, []
, {}
) __ nonzero __ ()
или __ len __ ()
, который возвращает 0 или False
Дополнительные сведения см. В разделе Проверка истинности документации Python. В частности:
Операции и встроенные функции, которые имеют логический результат, всегда возвращают
0
илиFalse
для false и1
илиTrue
за истину, если не указано иное. (Важное исключение: логические операцииили
,и
всегда возвращают один из своих операндов.)
Попробуйте использовать круглые скобки, чтобы выражение не было неоднозначным. Таким образом, вы получите:
(foo == bar and spam) or eggs