В программировании нам часто приходится принимать решения на основе нескольких условий. Например, мы можем захотеть выполнить какое-то действие только при одновременном выполнении нескольких условий. Или же мы можем захотеть запустить это действие при выполнении любого из нескольких условий.
Для работы с такими сценариями Python предлагает набор логических операторов — and
, or
, not
.
Из этого руководства вы узнаете, как работают логические операторы Python и как их использовать в программировании. Обратите внимание, что для концептуального представления этих операторов мы будем использовать слова AND, OR и NOT, написанные в верхнем регистре. А ключевые слова Python мы будем обозначать так: and
, or
и not
.
Содержание
- Что такое логические операторы Python? (Краткий ответ)
- Логический оператор and в Python
- Оператор or в Python
- Оператор not в Python
- Приоритет логических операторов в Python
- Заключение
Прежде чем перейти к деталям, давайте начнем с очень краткого ответа для тех, кто торопится.
Что такое логические операторы Python? (Краткий ответ)
Логические операторы Python (and
, or
, not
) — это специальные ключевые слова, которые играют роль союзов в нашем коде, соединяя и оценивая несколько условий в одном выражении.
Рассмотрим пример:
temperature = 25 is_sunny = True if temperature > 20 and is_sunny: print("It's a perfect day for a picnic!")
It's a perfect day for a picnic!
Здесь оператор and
гарантирует, что сообщение будет напечатано только при выполнении обоих условий: температура выше 20 градусов и солнечно (and is_sunny
).
Рассмотрим еще один пример с использованием оператора or
:
has_umbrella = False if is_sunny or has_umbrella: print("Let's go for a walk!")
Let's go for a walk!
В данном случае мы отправимся на прогулку, если либо будет солнечно, либо у нас будет зонтик (is_sunny or has_umbrella
).
Наконец, оператор not
переворачивает истинностное значение условия:
if not is_sunny: print("Maybe we should stay indoors.")
Здесь сообщение будет напечатано только в том случае, если не будет солнечно (not is_sunny
).
Логические операторы дают нам лаконичный и мощный способ выражения сложных условий, позволяя нашим программам принимать решения на основе множества факторов. А теперь давайте копнем глубже. Начнем с логического оператора and
.
Логический оператор and в Python
В булевой логике операция AND заключается в сравнении двух значений или выражений. Она дает истинный результат только в том случае, если оба значения истинны. Если одно или оба значения ложны, результат операции AND будет ложью. Вот краткое описание того, как ведет себя операция AND:
Операция | Выходное значение |
---|---|
true AND true | true |
true AND false | false |
false AND true | false |
false AND false | false |
Мы можем воссоздать эту таблицу истинности с помощью оператора and
:
options = True, False for a in options: for b in options: print(f"{a} and {b} gives {a and b}")
True and True gives True True and False gives False False and True gives False False and False gives False
Переменная options
содержит два булевых значения. Вложенные циклы for
дважды перебирают options
, чтобы создать все перестановки True и False.
Часто выражения, используемые в качестве операндов для and
, включают операторы сравнения или равенства:
names = "James", "Bob", "David", "Jane", "Kate", "Mary" for name in names: if len(name) < 5 and name[0] == "J": print(name)
Jane
Имя печатается только в том случае, если оно содержит менее пяти букв и начинается с буквы «J». Оба требования должны быть выполнены.
Выражения с операторами сравнения и равенства, такими как <
и ==
, оцениваются в True или False.
Но оператор and
работает с любым типом данных, а не только с булевыми True и False. Выходное значение также может быть любым типом данных.
Давайте теперь рассмотрим оператор and
более подробно. Начнем с обсуждения истинности.
Истинность и ложность в Python
Каждый объект Python можно привести к типу Boolean с помощью встроенного метода bool()
. Объект является истинным, если bool(object)
возвращает True. Для ложного объекта bool(object)
возвращает False.
Оператор and
в Python проверяет истинность своих операндов. Если оба операнда истинны, оператор and
также возвращает истинное значение. Если один или оба операнда ложные, оператор and
возвращает ложное значение. Давайте рассмотрим несколько примеров:
if 42 and "python": print("Both operands are truthy") else: print("One or both operands are falsy")
Both operands are truthy
Еще один пример:
if 42 and "": print("Both operands are truthy") else: print("One or both operands are falsy")
One or both operands are falsy
И последний пример:
if 0 and "python": print("Both operands are truthy") else: print("One or both operands are falsy")
One or both operands are falsy
Числовые типы, такие как целые числа и числа с плавающей запятой, являются истинными, если они ненулевые, и ложными, если равны нулю. Последовательности, такие как строки, истинны, если они непустые, и ложны, если пустые.
Таким образом, только первый из трех приведенных примеров удовлетворяет условию, что оба операнда должны быть истинными, чтобы оператор and
имел истинностное значение.
Оператор and
не всегда возвращает булево значение. Выражение, включающее and
, может также оценивать один из операндов. Давайте разберемся в этом на тех же примерах, которые мы использовали ранее. Вместо того чтобы использовать выражения и в операторе if
, мы будем оценивать их напрямую:
print(42 and "python") print(42 and "") print(0 and "python")
python 0
Заметили, что происходит с этими выражениями?
Начнем с последнего из трех примеров, в котором операндами являются 0 и «python». Оператор and
ищет два истинных операнда. Первый из них — 0, он ложный. Программе нет необходимости проверять второй операнд, поскольку все выражение будет ложным независимо от значения второго операнда.
Однако оператор and
не возвращает False. Вместо этого он возвращает непосредственно первый операнд. Поскольку первый операнд ложный, все выражение and
оценивается как ложное. В Python это не вызывает никаких проблем, поскольку в ситуациях, когда Python требует истинного или ложного значения, он может использовать истинность объекта.
В первом примере первый операнд равен 42, что является истиной. Программа оценивает второй операнд и возвращает его. Поскольку вторым операндом является строка «python», которая является истиной, все выражение оценивается как истинное.
Во втором примере первый операнд также равен 42. Поскольку он оценивается как истина, программа оценивает и возвращает второй операнд, который является пустой строкой. Пустая строка является ложной, и поэтому все выражение and
оценивается как ложное.
Если первый операнд истинный, оператор and
всегда возвращает значение второго операнда, независимо от того, истинный он или ложный.
Когда первый операнд ложный, Python не оценивает второй операнд. Это называется вычислением по короткой схеме, и это одна из форм ленивых вычислений. Вы можете убедиться в этом с помощью следующего кода:
0 and 5/0
0
Второй операнд равен 5/0, что обычно вызывает ошибку ZeroDivisionError. Однако в этом примере выражение 5/0 не оценивается, поскольку первый операнд является ложным. Исключение не возникает.
Пример: интернет-магазин для программистов
Рассмотрим простой пример, который представляет собой реальное приложение. Транзакции в интернет-магазине, поставляющем товары для программистов, регистрируются и доступны через API. Данные преобразуются в список словарей. Каждый элемент в списке представляет собой транзакцию, а каждая транзакция — словарь, содержащий соответствующую информацию:
data = [ {"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True}, {"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False}, {"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True}, {"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True}, ]
Каждая транзакция содержит название товара и его цену, количество единиц товара в заказе, а также информацию о том, была ли транзакция успешной.
Предположим, что нам нужны успешные транзакции для товаров стоимостью 100 долларов и выше. Мы можем использовать оператор and
для фильтрации нужных нам строк:
for item in data: if item["Success"] and item["Price"] >= 100: print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True}
Вывод этого кода показывает единственную транзакцию, удовлетворяющую обоим требованиям. Для каждого элемента в списке транзакций оператор if
проверяет истинность двух выражений:
- Значения, связанные с ключом «Success» в каждом словаре, являются либо True, либо False.
- Оператор
>=
вitem[«Price»] >= 100
также возвращает True или False.
Книга по Python и кабели не удовлетворяют требованию цены, поскольку их стоимость меньше 100 долларов. Кофемашина превышает этот ценовой порог, но транзакция не была успешной, поэтому она исключена из вывода.
Оператор or в Python
Логический оператор OR в булевой логике нуждается в двух операндах. Он принимает значение true, если хотя бы один из операндов оценивается как true:
Операция | Выходное значение |
---|---|
true OR true | true |
true OR false | true |
false OR true | true |
false OR false | false |
Мы можем воссоздать эту таблицу истинности с помощью оператора or
:
options = True, False for a in options: for b in options: print(f"{a} or {b} gives {a or b}")
True or True gives True True or False gives True False or True gives True False or False gives False
Мы также можем вернуться к примеру с именами людей, который мы рассматривали ранее, но заменить оператор and
на or
:
names = "James", "Bob", "David", "Jane", "Kate", "Mary" for name in names: if len(name) < 5 or name[0] == "J": print(name)
James Bob Jane Kate Mary
Теперь оператор if
содержит выражение or
. Таким образом, цикл for
выводит все имена, которые либо состоят из менее чем пяти букв, либо начинаются с буквы «J». Строка «Jane» удовлетворяет обоим требованиям. Остальные выведенные имена удовлетворяют одному из двух требований.
Истинность, ложность и оператор or в Python
Оператор or
также ищет истинные и ложные значения, а не только булевы True и False. Давайте рассмотрим несколько примеров:
if 42 or [10, 20, 30]: print("At least one operand is truthy") else: print("None of the operands is truthy")
At least one operand is truthy
И еще один пример:
if 42 or []: print("At least one operand is truthy") else: print("None of the operands is truthy")
At least one operand is truthy
И последний:
if 0 or []: print("At least one operand is truthy") else: print("None of the operands is truthy")
None of the operands is truthy
В первом примере целое число 42 и непустой список [10, 20, 30]
являются истинными. Поскольку оператор or
требует, чтобы хотя бы один операнд был истинным, все выражение оценивается как истинное.
Во втором примере число 42 истинно, но пустой список []
ложен, поскольку это пустая последовательность. Так как один из двух операндов является истинным, все выражение or оценивается как истинное.
В последнем примере и 0, и []
являются ложными. Поэтому все выражение оценивается как ложное.
Оператор or
также использует вычисление по короткой схеме при оценке выражения, чтобы избежать лишних вычислений. Давайте рассмотрим несколько примеров, чтобы проиллюстрировать этот момент:
print(42 or [10, 20, 30]) print(42 or []) print([] or 42) print([] or 0)
42 42 42 0
В первом примере первый операнд равен 42, что является истиной. Поскольку для определения окончательной истинности всего выражения or
требуется, чтобы истинным был только один операнд, этот первый операнд возвращается немедленно. Второй операнд не оценивается, поскольку его значение не влияет на конечный результат.
Оператор or
возвращает первый операнд, 42, а не булево значение True. В Python любое истинностное значение имеет тот же эффект, что и булево значение True в таких ситуациях, как использование операторов if
и while
.
Во втором примере первый операнд также равен 42, и выражение возвращает это целое число, несмотря на то что второй операнд является ложным.
В третьем и четвертом примерах первым операндом является пустой список, который является ложным. Поэтому в обоих случаях возвращается второй операнд.
Пример: интернет-магазин для программистов
Давайте вернемся к транзакциям из интернет-магазина. Вот четыре примера транзакций, которые мы используем в этом примере:
data = [ {"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True}, {"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False}, {"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True}, {"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True}, ]
Вам нужно определить несколько транзакций для дальнейшего изучения поведения покупателей. Вы хотите найти транзакции, которые либо не прошли, либо включают товар по цене ниже 75 долларов. Поскольку у вас есть два условия, а транзакция должна удовлетворять хотя бы одному из них, вы можете использовать оператор or
:
for item in data: if item["Success"] == False or item["Price"] < 75: print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True} {'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False} {'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
Этот цикл for
выводит строки, которые соответствуют хотя бы одному из требований. Книга по Python и кабели включены, так как их цена ниже 75 долларов. Кофемашина включена, поскольку транзакция не была успешной.
Есть и альтернативный способ фильтрации неудачных транзакций, который мы рассмотрим в следующем разделе.
Оператор not в Python
Оператор NOT отличается от AND и OR тем, что ему требуется только один операнд. NOT преобразует true в false и наоборот. Вот таблица истинности для NOT:
Операция | Выходное значение |
---|---|
NOT true | false |
NOT false | true |
Мы можем повторить это с помощью оператора not
:
options = True, False for a in options: print(f"not {a} evaluates to {not a}")
not True evaluates to False not False evaluates to True
Истинность, ложность и оператор not в Python
Как и в случае с and
и or
, операнд, используемый в операторе not
, не обязательно должен быть булевым. С not
можно использовать любой объект, поскольку любой объект является либо истинным, либо ложным.
if not "python": print("The `if` statement evaluated as `True`") else: print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `False`
Давайте также рассмотрим пример:
if not "": print("The `if` statement evaluated as `True`") else: print("The `if` statement evaluated as `False`")
The `if` statement evaluated as `True`
Истинные значения преобразуются в False с помощью оператора not
, а ложные значения преобразуются в True.
В отличие от операторов and
и or
, оператор not
всегда возвращает булев объект:
print(not "python") print(not "")
False True
Пример: интернет-магазин для программистов
В предыдущих разделах мы использовали транзакции из интернет-магазина. В этом примере мы хотим отобразить все неудачные транзакции. Один из вариантов — использовать оператор равенства ==
, чтобы проверить, равно ли data[«Success»]
False. Однако вместо этого можно использовать оператор not
:
data = [ {"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True}, {"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False}, {"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True}, {"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True}, ] for item in data: if not item["Success"]: print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
Поскольку для неуспешных транзакций item[«Success»]
равен False, то not item[«Success»]
возвращает True. Поэтому цикл for
выводит неудачные транзакции:
В следующем разделе мы рассмотрим, как объединить несколько логических операторов в одном выражении.
Приоритет логических операторов в Python
В примерах, показанных до сих пор, мы использовали логические операторы по одному. В этом разделе мы посмотрим, что происходит, когда мы объединяем несколько логических операторов в одном выражении.
and имеет приоритет над or
Продолжим работу с транзакциями из интернет-магазина. Попробуем выполнить следующее условное предложение:
data = [ {"Item": "Python Book", "Price": 50, "Quantity": 1, "Success": True}, {"Item": "Coffee Machine", "Price": 125, "Quantity": 1, "Success": False}, {"Item": "Headphones", "Price": 250, "Quantity": 1, "Success": True}, {"Item": "Cables", "Price": 15.99, "Quantity": 3, "Success": True}, ] for item in data: if item["Price"] > 100 or item["Quantity"] > 2 and item["Success"]: print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False} {'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True} {'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
Оператор if
содержит два логических оператора. Прежде чем мы изучим, как Python работает с этим выражением, давайте проговорим суть предложения if
простым языком: “Если цена товара больше 100 долларов или количество проданных товаров больше двух и продажа прошла успешно, то распечатай товар”.
Эта фраза неоднозначна, и даже если добавить в предложение больше запятых, все равно может возникнуть путаница. Например, нужно ли включать в вывод транзакцию с кофемашиной? Цена товара превысила требуемый порог, но транзакция не была успешной.
Python разрешил эту двусмысленность, предоставив оператору and
приоритет над оператором or
. Это означает, что выражение and
оценивается первым, а его результат используется в выражении or
.
Поэтому выражение item[«Quantity»] > 2 and item[«Success»]
оценивается первым. Это выражение возвращает истинное значение только для транзакции, включающей кабели. Для остальных элементов оно оценивается как ложное.
Значение из выражения and
затем используется с оператором or
. Выражение or
возвращает истинное значение для любого элемента, для которого выражение and
возвращает истинное значение (для транзакции, включающей кабели), и для элементов, цена которых превышает 100 долларов. Есть два предмета, цена которых превышает пороговое значение: кофемашина и наушники.
Логические операторы и круглые скобки
Однако что делать, если нам нужны транзакции с товарами по цене выше 100 долларов или с количеством больше двух, но в обоих условиях мы хотим убедиться, что транзакция прошла успешно? В этом случае нужно, чтобы выражение or
имело приоритет над выражением and
, чтобы оно оценивалось первым. Мы можем добиться этого, используя круглые скобки вокруг выражения or
:
for item in data: if (item["Price"] > 100 or item["Quantity"] > 2) and item["Success"]: print(item)
{'Item': 'Headphones', 'Price': 250, 'Quantity': 1, 'Success': True} {'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
Дополнительные круглые скобки дают приоритет выражению or
. Транзакция с кофемашиной больше не включается, поскольку по ней второй операнд and
оценивается как ложный.
Оператор not имеет приоритет над операторами and и or
Оператор not
имеет приоритет над операторами and
и or
. Поэтому not
оценивается раньше двух других логических операторов.
Рассмотрим следующее предложение if
, содержащее not
и and
:
for item in data: if not item["Success"] and item["Price"] > 100: print(item)
{'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False}
Поскольку not
оценивается первым, это выражение сначала применит оператор not
к item[«Success»]
. Затем значение из выражения not
используется в качестве первого операнда в выражении and
. Этому условию удовлетворяет только запись о кофемашине — это единственная транзакция, которая завершилась неудачей и имеет цену более 100 долларов.
Однако мы можем дать приоритет оператору and
, используя круглые скобки:
for item in data: if not (item["Success"] and item["Price"] > 100): print(item)
{'Item': 'Python Book', 'Price': 50, 'Quantity': 1, 'Success': True} {'Item': 'Coffee Machine', 'Price': 125, 'Quantity': 1, 'Success': False} {'Item': 'Cables', 'Price': 15.99, 'Quantity': 3, 'Success': True}
В этом случае выражение and
оценивается первым. Только запись с наушниками получает значение True, поскольку это единственная успешная сделка с ценой более 100 долларов. Однако мы добавляем оператор not
перед выражением в круглых скобках. Поэтому код выводит оставшиеся три транзакции.
В общем, если выражение становится слишком сложным из-за большого количества операторов, лучше разделить его, чтобы сделать более читаемым.
Заключение
Логические операторы Python and
, or
и not
активно используются в широком спектре приложений для программирования и работы с данными. Эти операторы повторяют поведение булевых логических операторов AND, OR и NOT, широко используемых в логике и математике.
Однако операторы Python могут принимать любые объекты, а не только булевы значения. Операторы and
и or
используют вычисления по короткой схеме и возвращают один из операндов в качестве вывода.
Логические операторы Python являются ключевыми инструментами для фильтрации данных, выявления особенностей в наборах данных и создания сложных правил для управления ходом программы.
Перевод статьи “Python Logical Operators: A Hands-on Introduction”.