ЛОГИЧЕСКИЕ ОПЕРАТОРЫ В PYTHON
Логические операторы используются для объединения нескольких операторов сравнения. Существуют три логических оператора: or (ИЛИ), and (И), not (НЕ).
Логический оператор «or»
Возвращает True, если хотя бы одно из сравнений истинно. Если оба сравнения ложны, то результат операции будет False.
a = 5 > 7 or 2 < 3 print(a)
True
Логический оператор "and"
Возвращает True, если оба сравнения истинны. Если хотя бы одно из сравнений ложно, то результат операции будет False.
a = 5 > 7 and 2 < 3 print(a)
False
Логический оператор "not"
Инвертирует результат сравнения. Если сравнение истинно, то результат операции будет False. Если сравнение ложно, то результат операции будет True.
a = not 5 > 7 print(a)
True
Старшинство логических операций
Первой выполняется операция not, за ней — and. В последнюю очередь выполняется операция or.
Логические операторы младше операторов сравнения.
Что является результатом действия логического оператора or
В языке Python операторы and и or, как вы и ожидали, выполняют булевы операции, но они не возвращают булевы значения: результатом всегда является значение одного из операндов.
Пример 2.16. Оператор and
>>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c'
| При использовании оператора and, значения вычисляются в булевом контексте слева напрво. Значения 0, '', [], (), <> и None являются ложью, все остальное является истиной [3] . Если у and оба операнда являются истиной, результатом будет последнее значение. В данном случае вычисляется выражение 'a', которое является истиной, затем 'b', которое также является истиной, и возвращается 'b'. | |
| Если какой-либо из операндов является ложью, результатом будет первое такое значение. В данном случает '' — первое значение, являющееся ложью. | |
| Все значения являются истиной, так что в результате мы получаем последнее — 'c'. |
Пример 2.17. Оператор or
>>> 'a' or 'b' 'a' >>> '' or 'b' 'b' >>> '' or [] or <> <> >>> def sidefx(): . print "in sidefx()" . return 1 >>> 'a' or sidefx() 'a'
| Как и для and опреранды or вычисляются в булевском контексте слева направо. Если операнд является истиной, or немедленно возвращает результат. В данном случае 'a' — первое истинное значение. | |
| or вычисляет выражение '', которое является ложью, затем 'b', которое является истиной, и возвращает 'b'. | |
| Если все значения являются ложью, or возвращает последнее. or вычисляет '' (ложь), [] (ложь), затем <> (ложь) и возвращает <>. | |
| Обратите внимание, что or вычисляет операнды до тех пор, пока не найдет истинное значение, остальное игнорируется. Это имеет значение, когда вычисление операнда дает сторонние эффекты. В данном случае функция sidefx не вызывается, так как для получения результата выражения с опереатором or достаточно того, что первый операнд, 'a', является истиной. |
Если вы используете C, то, наверное, знакомы с выражением bool ? a : b, которое дает a, если bool является истиной, b, если bool ложно. Благодаря особенностям работы операторов and и or в Python, вы можете достигнуть анологичного эффекта.
Пример 2.18. Прием с and-or
>>> a = "first" >>> b = "second" >>> 1 and a or b 'first' >>> 0 and a or b 'second'
| Синтаксис bool ? a : b в языке Python выглядит похоже. Все выражение вычисляется слева направо, так что оператор and применяется первым. 1 and 'first' дает 'first', затем 'first' or 'second' дает 'first'. | |
| 0 and 'first' дает 0, тогда 0 or 'second' дает 'second'. |
Однако, так как такое выражение выполняет обычные логические операции, а не является специальной конструкцией языка, существует очень важная разница между приемом с and-or в языке Python и конструкцией bool ? a : b в C. Если значение a является ложью, это прием не будет работать так как вы могли ожидать. (Вы можете сказать, что обожгись на этом? Более одного раза?)
Пример 2.19. Когда прием с and-or не работает
>>> a = "" >>> b = "second" >>> 1 and a or b 'second'
| Так как a — пустая строка, которую Python считает ложью в булевом контексте, 1 and '' дает '', а '' or 'second' дает 'second'. Ой! Это не то, что мы хотели получить. |
| Прием с and-or, bool and a or b, не будет работать так же, как конструкция bool ? a : b в C, если a является ложью. | |
Для безопасного использования приема с and-or необходимо сделать так, чтобы a всегда было истинным. Один из самых распространенных способо это сделать — заменить a на [a] и b на [b], тогда первый элемент получаемого списка будет либо a, либо b.
Пример 2.20. Безопасное использование приема с and-or
>>> a = "" >>> b = "second" >>> (1 and [a] or [b])[0] ''
| Так как выражение [a] является непустым списком, оно никогда не будет ложно. Даже если a равно 0, '' или другому значению, являющемуся ложью, список [a] всегда будет являться истиной, потому что содержит один элемент. |
Кажется, этот прием не стоит того, чтобы его использовать. В конце концов вы всегда можете воспользоваться интсрукцией if. Тогда зачем вся эта суета? Конечно, в большинстве случаев выбирая между двумя константами вы можете использовать простой синтаксис и не беспокоиться, потому что значение a всегда будет истинным. И даже если придется использовать более сложный синтакс, на это могут найтись весские причины: в некоторых случаях в языке Python использование инструкции if не допускается, например в lambda-функциях.
- В Python Cookbook обсуждаются альтернативы приему с and-or.
[3] Ну, почти все. По умолчанию экземпляры классов являются истиной, но вы можете определить специальные методы в классе, чтобы его экземпляры могли быть ложью. Вы узнаете все о классах и специальных методах в главе 3.
Copyright © 2000, 2001, 2002 Марк Пилгрим
Copyright © 2001, 2002 Перевод, Денис Откидач
Python: Логические операторы
Мы уже умеем писать функции, которые проверяют одиночные условия. А в этом уроке научимся строить составные условия.
Предположим, что сайт при регистрации требует, чтобы пароль был длиннее восьми символов и содержал хотя бы одну заглавную букву. Попробуем написать два отдельных логических выражения и соединим их специальным оператором «И»:
Пароль длиннее 8 символов И пароль содержит хотя бы одну заглавную букву
Вот функция, которая принимает пароль и говорит, соответствует ли он условиям ( True ) или не соответствует ( False ):
def has_capital_letter(string): # Проверяет наличие хотя бы одной заглавной буквы в строке def is_correct_password(password): length = len(password) return length > 8 and has_capital_letter(password) print(is_correct_password('Qwerty')) # => False print(is_correct_password('Qwerty1234')) # => True print(is_correct_password('qwerty1234')) # => False
and — означает «И». В математической логике это называют конъюнкцией. Все выражение считается истинным, если истинен каждый операнд — каждое из составных выражений. Иными словами, and означает «и то, и другое». Приоритет этого оператора ниже, чем приоритет операторов сравнения. Поэтому выражение has_capital_letter(password) and length > 8 тоже правильно отрабатывает без скобок.
Кроме and часто используется оператор or — «ИЛИ» (дизъюнкция). Он означает «или то, или другое, или оба». Выражение a or b считается истинным, если хотя бы один из операндов или одновременно все — истинные. В другом случае выражение ложное.
Операторы можно комбинировать в любом количестве и любой последовательности. Если в коде одновременно встречаются and и or , то приоритет задают скобками. Ниже пример расширенной функции, которая определяет корректность пароля:
def has_capital_letter(string): # Проверяет наличие хотя бы одной заглавной буквы в строке def has_special_chars(string): # Проверяет содержание специальных символов в строке def is_strong_password(password): length = len(password) # Скобки задают приоритет. Понятно, что к чему относится. return (length > 8 and has_capital_letter(password)) and has_special_chars(password)
Теперь представим, что мы хотим купить квартиру, которая удовлетворяет таким условиям: площадь от 100 квадратных метров и больше на любой улице ИЛИ площадь от 80 квадратных метров и больше, но на центральной улице Main Street .
Напишем функцию, которая проверит квартиру. Она принимает два аргумента: площадь — число и название улицы — строку:
def is_good_apartment(area, street): return area >= 100 or (area >= 80 and street == 'Main Street') print(is_good_apartment(91, 'Queens Street')) # => False print(is_good_apartment(78, 'Queens Street')) # => False print(is_good_apartment(70, 'Main Street')) # => False print(is_good_apartment(120, 'Queens Street')) # => True print(is_good_apartment(120, 'Main Street')) # => True print(is_good_apartment(80, 'Main Street')) # => True
Область математики, в которой изучаются логические операторы, называется булевой алгеброй. Ниже увидите таблицы истинности — по ним можно определить, каким будет результат, если применить оператора:
И and
| A | B | A and B |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
ИЛИ or
| A | B | A or B |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
Задание
Реализуйте функцию is_leap_year() , которая принимает год в форме числа и определяет является ли он високосным или нет. Год будет високосным, если он кратен (то есть делится без остатка) 400 или он одновременно кратен 4 и не кратен 100. Как видите, в определении уже заложена вся необходимая логика, осталось только переложить её на код:
is_leap_year(2018) # false is_leap_year(2017) # false is_leap_year(2016) # true
Кратность можно проверять так:
# % - возвращает остаток от деления левого операнда на правый # Проверяем что number кратен 10 number % 10 == 0 # Проверяем что number не кратен 10 number % 10 != 0
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
- Булева алгебра
- Логическое «И»
- Логическое «ИЛИ»
Определения
- Логические операторы — операторы «И» ( and ), ИЛИ ( or ), позволяющие создавать составные логические условия.
Логические операторы
Здесь мы рассмотрим первые пять, операторы ?? и ??= будут в следующей статье.
Несмотря на своё название, данные операторы могут применяться к значениям любых типов. Полученные результаты также могут иметь различный тип.
Давайте рассмотрим их подробнее.
|| (ИЛИ)
Оператор «ИЛИ» выглядит как двойной символ вертикальной черты:
result = a || b;
Традиционно в программировании ИЛИ предназначено только для манипулирования булевыми значениями: в случае, если какой-либо из аргументов true , он вернёт true , в противоположной ситуации возвращается false .
В JavaScript, как мы увидим далее, этот оператор работает несколько иным образом. Но давайте сперва посмотрим, что происходит с булевыми значениями.
Существует всего четыре возможные логические комбинации:
alert( true || true ); // true alert( false || true ); // true alert( true || false ); // true alert( false || false ); // false
Как мы можем наблюдать, результат операций всегда равен true , за исключением случая, когда оба аргумента false .
Если значение не логического типа, то оно к нему приводится в целях вычислений.
Например, число 1 будет воспринято как true , а 0 – как false :
if (1 || 0) < // работает как if( true || false ) alert( 'истинно!' ); >
Обычно оператор || используется в if для проверки истинности любого из заданных условий.
let hour = 9; if (hour < 10 || hour >18)
Можно передать и больше условий:
let hour = 12; let isWeekend = true; if (hour < 10 || hour >18 || isWeekend) < alert( 'Офис закрыт.' ); // это выходной >
ИЛИ "||" находит первое истинное значение
Описанная выше логика соответствует традиционной. Теперь давайте поработаем с «дополнительными» возможностями JavaScript.
Расширенный алгоритм работает следующим образом.
При выполнении ИЛИ || с несколькими значениями:
result = value1 || value2 || value3;
Оператор || выполняет следующие действия:
- Вычисляет операнды слева направо.
- Каждый операнд конвертирует в логическое значение. Если результат true , останавливается и возвращает исходное значение этого операнда.
- Если все операнды являются ложными ( false ), возвращает последний из них.
Значение возвращается в исходном виде, без преобразования.
Другими словами, цепочка ИЛИ || возвращает первое истинное значение или последнее, если такое значение не найдено.
alert( 1 || 0 ); // 1 (1 - истинное значение) alert( true || 'какая-то строка' ); // true alert( null || 1 ); // 1 (первое истинное значение) alert( null || 0 || 1 ); // 1 (первое истинное значение) alert( undefined || null || 0 ); // 0 (поскольку все ложно, возвращается последнее значение)
Это делает возможным более интересное применение оператора по сравнению с «чистым, традиционным, только булевым ИЛИ».
-
Получение первого истинного значения из списка переменных или выражений. Например, у нас есть переменные firstName , lastName и nickName , все они необязательные (т.е. они могут быть неопределенными или иметь ложные значения). Давайте воспользуемся оператором ИЛИ || , чтобы выбрать ту переменную, в которой есть данные, и показать её (или «Аноним», если ни в одной переменной данных нет):
let firstName = ""; let lastName = ""; let nickName = "Суперкодер"; alert( firstName || lastName || nickName || "Аноним"); // Суперкодер