Три слова вместо символов
Логические операторы Python это английские слова and, or и not. В других языках они пишутся как &&, || и !. В Python && и || дают SyntaxError, а ! встречается только в составе != («не равно»).
С True и False правила такие, каких ты и ждёшь:
a | b | a and b | a or b | not a |
|---|---|---|---|---|
True | True | True | True | False |
True | False | False | True | False |
False | True | False | True | True |
False | False | False | False | True |
and требует, чтобы истинными были обе стороны. or требует хотя бы одну. not принимает одно значение и инвертирует его.
В реальном коде сторонами обычно служат сравнения, а результат идёт в if или while:
Вывод:
eligible
standard ticket
Для большинства условий этого достаточно. Остальная часть страницы о том, что операторы делают со значениями, которые не являются True или False, и о правилах, решающих, какая сторона выражения выполнится.
Truthy и falsy значения
and, or и not принимают любые значения, а не только булевы. Считать ли значение истинным, Python решает по его истинности (truthiness). Эти значения falsy:
FalseиNone- ноль любого числового типа:
0,0.0 - пустые контейнеры и строки:
"",[],(),{},set(),range(0)
Всё остальное truthy, в том числе "0", "False", [0] и -1. Как Python классифицирует значение, можно увидеть через bool():
Вывод:
0 False
1 True
-1 True
'' False
'0' True
[] False
[0] True
None False
0.0 False
Строка "0" truthy, потому что это непустая строка. На этом попадаются те, кто читает числа из ввода и проверяет их до преобразования. Как bool связан с int, разобрано на странице про числа и булевы значения.
and и or возвращают операнд
Здесь Python отличается от большинства языков. and и or не создают новый True или False. Они возвращают одно из двух значений, которые ты им передал:
x or yвозвращаетx, еслиxtruthy, иначе возвращаетy.x and yвозвращаетx, еслиxfalsy, иначе возвращаетy.
Когда оба операнда булевы, «вернуть операнд» и «вернуть булево значение» означают одно и то же, поэтому разницу не замечают, пока не подмешают другие типы.
not составляет исключение: он всегда возвращает True или False.
Если из выражения с and/or нужно настоящее булево значение, например чтобы сохранить его или вернуть из функции, которая обещает bool, оберни его в bool():
Вычисление по короткой схеме
Python вычисляет and и or слева направо и останавливается, как только ответ известен:
andостанавливается на первом falsy значении, потому что ничто после него уже не сделает всё выражение истинным.orостанавливается на первом truthy значении, потому что ничто после него уже не сделает всё выражение ложным.
Пропущенная сторона вообще не выполняется. Это можно увидеть на функциях, которые печатают сообщение при вызове:
Вывод:
and:
checking A
False
or:
checking A
True
B не проверяется ни в одном из случаев. Именно короткое замыкание делает защитные условия безопасными. Вторая половина каждого условия ниже сама по себе упала бы, но выполняется она только после того, как первая половина исключила плохой случай:
Ставь дешёвую или защитную проверку первой. Если поменять порядок, user.startswith("admin") and user is not None выбросит AttributeError, когда user равен None.
Приёмы на основе or и and
Поскольку or возвращает свой первый truthy операнд, он даёт значение по умолчанию в одну строку:
Вывод:
Hello, Ada!
Hello, guest!
Hello, guest!
Подвох в том, что or заменяет любое falsy значение, а не только None. Если 0, "" или [] допустимый ввод, or его выбросит:
Используй x if x is not None else default, когда ноль или пустое значение допустимы. Это условное выражение разобрано на странице про if/else.
У and есть парный приём: «используй это значение, только если первое задано». Он встречается реже и часто понятнее в виде if, так что прибегай к нему нечасто:
Приоритет: not, затем and, затем or
Когда выражение смешивает все три оператора, Python применяет сначала not, затем and, затем or. Сравнения вроде ==, < и in применяются раньше любого из них.
a or b and c и (a or b) and c дают разные ответы на одних и тех же значениях, поэтому смешанное условие стоит снабжать скобками, даже если порядок по умолчанию оказался правильным. Скобки ничего не стоят и снимают вопрос у следующего читателя.
and/or против &/|
& и | похожи на and и or и иногда дают тот же ответ, но это разные операторы.
andиorпроверяют истинность, вычисляются по короткой схеме и возвращают один из операндов.&и|это побитовые операторы. Для целых чисел они комбинируют биты двух чисел. Для множеств они означают пересечение и объединение. ДляTrueиFalseони возвращают булево значение. По короткой схеме они не вычисляются никогда: обе стороны вычисляются всегда.
У побитовых операторов к тому же приоритет выше, чем у сравнений, и условие, записанное через &, превращается в нечто совсем другое:
1 & y это 1 & 5, то есть 1, поэтому средняя строка превращается в цепочку 5 > 1 > 1, а 1 > 1 ложно. В обычном коде на Python для условий используй and, or и not.
Единственное место, где &, | и ~ правильны для условий, это NumPy и pandas. Массив содержит много значений, поэтому у него нет единого значения истинности, и and выбрасывает ValueError: The truth value of an array ... is ambiguous. Библиотеки перегружают & и |, чтобы они работали поэлементно, поэтому фильтры в pandas выглядят как df[(df.age > 18) & (df.country == "CA")], со скобками вокруг каждого сравнения по той же причине приоритета.
any() и all(): and и or по списку
Чтобы объединить целую последовательность условий, используй встроенные функции all() (and по всем элементам) и any() (or по всем элементам). Обе вычисляются по короткой схеме точно так же:
В отличие от and и or, any() и all() всегда возвращают булево значение.
Частые ошибки
Сравнение одной переменной с несколькими значениями через or. Это условие всегда истинно:
Python читает первое условие как (color == "red") or "blue". Сравнение даёт False, поэтому or возвращает "blue", непустую строку, а она truthy. Повтори сравнение с обеих сторон или, что лучше, проверь вхождение через in.
Запись && или ||. Оба дают SyntaxError. Используй and и or.
Ожидание булева значения от and/or. x = a or b сохраняет сам a или сам b. Часто это то, что нужно, но если функция должна вернуть True или False, преобразуй результат через bool().
Надежда на приоритет в смешанных условиях. a or b and c допустимо и однозначно определено, но добавь скобки, чтобы никому не пришлось вспоминать правило.
Часто задаваемые вопросы
Что делает оператор and в Python?
a and b истинно, только когда истинны обе стороны. Python сначала вычисляет a; если a falsy, он возвращает a, даже не глядя на b, иначе возвращает b. С обычными булевыми значениями получается привычный результат: True and False равно False.
Почему 0 or 5 возвращает 5, а не True?
0 or 5 возвращает 5, а не True?or и and возвращают один из своих операндов, а не новое булево значение. x or y возвращает x, если x truthy, иначе y. 0 falsy, поэтому 0 or 5 возвращает 5. Оберни выражение в bool(), если нужен настоящий True или False.
Чем and отличается от & в Python?
and отличается от & в Python?and это логический оператор: он проверяет истинность и вычисляется по короткой схеме. & это побитовый оператор: для целых чисел он комбинирует биты (6 & 3 равно 2), для множеств находит пересечение и всегда вычисляет обе стороны. В условиях if используй and. Исключение составляют NumPy и pandas, где & означает поэлементное «и».
Что выполняется первым в Python, and или or?
Сильнее всех связывает not, затем and, затем or. Поэтому a or b and c означает a or (b and c), а not a or b означает (not a) or b. Сравнения вроде == и < связывают сильнее всех трёх.
Можно ли использовать && и || в Python?
Нет. && и || в Python дают SyntaxError. Логические операторы записываются словами and, or и not. Одиночные & и | допустимы, но означают другое (побитовые «и» и «или»).