Углубление в логические операторы Python

Конспект посвящён скрытым особенностям и неочевидным деталям логических операторов в Python
Truthy и falsy объекты
Falsy — объекты, которые могут быть оценены как значение False. К ним относятся следующие объекты:
- Значение
False - Значение
None - Числовые нули:
0,0.0,0j,Decimal(0),Fraction(0, 1) - Пустые последовательности и коллекции:
b'',bytearray(b''),'',[],(),{},set(),range(0)
Truthy — объекты, которые могут быть оценены как значение True. К ним относятся все объекты, не относящиеся к falsy.
Чтобы представить такие объекты в булевом виде, можно использовать функцию bool().
Операторы and и or
Операторы and и or не приводят свои результаты принудительно к значениям True или False, а возвращают один из своих операндов. Такой подход позволяет использовать эти операторы в более общих операциях, а не только в булевых.
Для начала посмотрим на оператор or:
|
|
|
|
Как можно видеть, оператор or оценивает каждый свой операнд как truthy или falsy объект, однако возвращает не значение True или False, а сам объект по определенному правилу — первый truthy объект либо последний объект, если truthy объекты в логическом выражении не найдены.
Подобным образом с помощью or можно определять значение по умолчанию, к примеру:
|
|
Если пользователь ничего не передаст в функцию input(), в переменную greet попадёт строка "noname".
Перейдём к оператору and:
|
|
|
|
Оператор and возвращает первый falsy объект либо последний объект, если falsy объекты в логическом выражении не найдены.
Short-circuit evaluation
Операторы and и or укорачивают вычисление своих операндов (т.е. используют замыкания): правый операнд вычисляется лишь в том случае, если его значение необходимо для получения истинного значения в операциях and или or. Другими словами, замыкания в логических операциях используются для запуска второй части или последующих частей логического выражения только в том случае, если это актуально!
- Если левый операнд оператора
orявляетсяtruthyобъектом, то общим результатом логического выражения являетсяTrue, независимо от значения правого операнда. - Если левый операнд оператора
andявляетсяfalsyобъектом, то общим результатом логического выражения являетсяFalse, независимо от значения правого операнда.
Данный механизм называется вычислением по короткой схеме (short-circuit evaluation) и используется интерпретатором для оптимизации вычислений. Рассмотрим пример:
|
|
Левым операндом оператора or является truthy объект, значит, для вычисления общего результата логического выражения нет необходимости вычислять правый операнд, то есть вызывать функцию f(). Поскольку вызова функции не происходит, в выводе отсутствует строка bee.
И наоборот, если заменить or на and, в выводе будут обе строки.
Приоритет логических операторов
Приоритет указан от наивысшего к наименьшему:
notandor
По отношению к другим операторам Python (за исключением оператора присваивания =) логические операторы имеют самый низкий приоритет.
|
|
В этом коде сначала сравниваются значения переменных, затем применяется оператор not.
Стоит упомянуть, что подобная запись будет вызывать исключение SyntaxError:
|
|
Рассмотрим ещё один пример:
|
|
Согласно приоритету операторов в первую очередь вычисляются выражения 1 == 2, 3 == 3 и 5 == 6, в результате чего исходное выражение принимает вид not False or True and False. Далее выполняется оператор not, возвращая значение True, после него — оператор and, возвращая значение False. Выражение принимает вид True or False. Последним выполняется оператор or, возвращая общий результат выражения — значение True.
P.S. На самом деле после вычисления not 1 == 2 оператор or сразу вернёт True, не вычисляя правую часть.
Цепочки сравнений
Как известно, сравнивать объекты в Python можно в укороченной форме, например вместо a < b and b < c писать a < b < c
Поскольку оператор and реализует вычисление по короткой схеме, все сравнения, которые располагаются правее сравнения, вернувшего ложный результат, не выполняются, и их операнды не вычисляются:
|
|
Пояснение: выражение 5 < 1 < f() эквивалентно выражению 5 < 1 and 1 < f(). Сравнение 5 < 1 возвращает False. В результате сравнение 1 < f() не выполняется, и функция f() не вызывается.
Тем не менее между сокращенным и расширенным вариантами записи цепочек сравнений существует важное отличие. В сокращенном выражении значение, стоящее по середине (между операторами сравнения), будет вычислено один раз (если его вообще нужно вычислять), а в развёрнутом выражении — два раза:
|
|
|
|
Помимо операторов сравнения, в цепочку операторов могут объединяться и другие операторы Python.
|
|
Данное выражение на самом деле эквивалентно выражению num in lst and lst == True, которое, в свою очередь, эквивалентно выражению True and False. Следовательно, результатом данной цепочки операторов является значение False.
Рассмотрим ещё один пример:
|
|
|
|
Основной источник: https://habr.com/ru/articles/824170/
Доп. источники:
cloudtips