К содержанию

Модуль 2 · Урок 2.1

Логические выражения

Сравнения дают True или False; and, or и not собирают из них условия, а короткое вычисление защищает от ошибок.

6 задач

До сих пор программа выполняла все строки подряд. Но часто действие зависит от данных: хватит ли денег, делится ли число, попадает ли балл в нужный диапазон. Чтобы программа могла выбирать, ей нужны ответы «да» или «нет». Такие ответы дают сравнения, а and, or и not собирают из простых ответов сложные. Как программа выбирает действия по ответу, разберём в следующем уроке.

Проверять условия будем на числе x = 12: чётно ли оно, делится ли на 3, лежит ли между 5 и 20.

Сравнения

Сравнение отвечает на вопрос «да» или «нет». Ответ — одно из двух значений: True («да», истина) или False («нет», ложь). Это не текст, а значения особого типа bool — того, что в уроке о типах был обещан на потом:

temperature = 18is_warm = temperature >= 15print(is_warm)print(type(is_warm))
True <class 'bool'>

= присваивает, == сравнивает. В записи is_warm = temperature >= 15 правая часть отвечает на вопрос, а = связывает имя с ответом. Всего сравнений шесть:

x = 12print(x == 12)  # равноprint(x != 12)  # не равноprint(x < 20)   # меньшеprint(x > 20)   # большеprint(x <= 12)  # меньше или равноprint(x >= 15)  # больше или равно
True False True False True False

Знаки из двух символов пишутся слитно: <=, а не < =.

Сравнивать имеет смысл значения одного типа. Строка никогда не равна числу: "40" == 40 даёт False, хотя на экране оба выглядят как 40. Поэтому число из input сначала превращают через int, как в прошлом уроке.

and, or, not

and требует обоих условий, or — хотя бы одного, not меняет ответ на противоположный. Возьмём два простых условия для x = 12: a — «x чётно», b — «x больше 20»:

x = 12a = x % 2 == 0b = x > 20print(a and b)print(a or b)print(not b)
False True True

a истинно, b ложно. and требует обоих — ответ False; or хватает одного — True; not переворачивает ложное b в True. У двух условий всего четыре сочетания; разложим их клетками и отметим, где выражение истинно:

and истинно в одной клетке — когда истинны оба. or ложно в одной клетке — когда ложны оба. a != b истинно на диагонали: ровно одно из двух. Точка — наш случай x = 12: a истинно, b ложно.

Обрати внимание на нижнюю правую клетку or: or истинно и тогда, когда верны оба условия, — это не «одно из двух». «Ровно одно из двух» записывают как a != b: ответы двух условий различаются.

Тонкости:!= для чисел

«Ровно одно» != означает только между логическими значениями. Между числами это просто «числа различаются»: 3 != 5 — это True, и никакого «одного из двух» тут нет.

Интервал записывают цепочкой сравнений:

x = 12print(5 <= x < 20)print(5 <= x and x < 20)
True True

5 <= x < 20 — то же, что 5 <= x and x < 20: выполняются оба сравнения.

Закрашенный конец 5 входит в интервал (<=), пустой конец 20 — нет (<). 12 лежит внутри, поэтому ответ True.

Порядок and, or, not

Сначала вычисляются сравнения, затем not, затем and и только потом or. Это похоже на арифметику, где умножение сильнее сложения: and сильнее or. Проверим на правиле високосного года: год високосный, если делится на 4 и не делится на 100 — или если делится на 400:

y = 2000print(y % 4 == 0 and y % 100 != 0 or y % 400 == 0)x = 12print(not x % 3 == 0)
True False

В первой записи Python сначала вычисляет три сравнения, затем and из первых двух, затем or с третьим. Во второй not применяется к готовому сравнению x % 3 == 0: 12 делится на 3, сравнение даёт True, а not превращает его в False.

Как в арифметике, операция выполняется, когда готовы значения под ней. Для 2000 первая пара сравнений даёт True и False, and — False, но третье сравнение истинно, и or даёт True. Слева not стоит над всем сравнением.

Если сомневаешься в порядке, ставь скобки: (y % 4 == 0 and y % 100 != 0) or y % 400 == 0 читается сразу, без знания правил.

Короткое вычисление

Python не вычисляет часть условия, которая уже не влияет на ответ. В a and b значение b не нужно, если a ложно. В a or b значение b не нужно, если a истинно. Это называют коротким вычислением.

x = 0print(x != 0 and 10 / x > 2)print(x == 0 or 10 / x > 2)
False True
Как только левой части хватает для ответа, правая пропускается. Поэтому 10 / x при x = 0 не выполняется ни в одной строке.

Деления на ноль нет ни в одной строке: правая часть не вычислялась. Порядок частей значим: проверка, которая защищает от ошибки, должна стоять раньше действия, которое без неё упадёт. Если переставить части, 10 / x > 2 and x != 0 остановится с ZeroDivisionError.

Истинность значений

Любое значение в условии считается истинным или ложным. Ноль, пустая строка и None считаются ложными; ненулевые числа и непустые строки — истинными. Позднее к ложным добавятся пустые коллекции.

Ложных значений немного, их легко запомнить: ноль, пустая строка, None и сам False. Всё остальное истинно, в том числе строки "0", "False" и строка из одного пробела.

bool(value) показывает, истинно ли значение. bool("False") равно True: строка непустая, а английское слово в ней Python не читает.

or и and возвращают одну из своих частей, а не обязательно True или False. or с ложной левой частью отдаёт правую, and с ложной левой частью отдаёт её саму: 0 and 5 — это 0. Со сравнениями этого не видно: их части и так True или False. Зато отсюда частая ошибка: «x равно 2 или 3» хочется записать как x == 2 or 3:

x = 12print(x == 2 or 3)print(x == 2 or x == 3)
3 False

Python читает первую запись как (x == 2) or 3. Левая часть ложна, и or отдаёт правую — само число 3. А 3 в условии истинно, поэтому такое «условие» выполняется при любом x. Сравнение нужно повторить: x == 2 or x == 3.

Тонкости:запасное значение через or

Точное правило: or возвращает первую истинную часть, а если такой нет — последнюю; and — первую ложную или последнюю. На этом держится запись запасного значения: "" or "Без названия" даёт «Без названия», а 5 and 8 — 8.

Отрицание и импликация

Отрицание составного условия меняет and на or. Выражение not (a and b) истинно, когда хотя бы одно из условий ложно; оно равносильно (not a) or (not b). Аналогично not (a or b) равносильно (not a) and (not b). Проверим на x = 12: «неверно, что x чётно и больше 20» — то же, что «x нечётно или не больше 20»:

x = 12print(not (x % 2 == 0 and x > 20))print(x % 2 != 0 or x <= 20)
True True

Импликация «если A, то B» ложна только при истинном A и ложном B. Её можно записать (not A) or B.

Единственная ложная клетка — A истинно, B ложно: обещание «если A, то B» нарушено. Если A ложно, обещание не проверяется, и импликация истинна.

В задачах ЕГЭ о логике (например, в задачах 2 и 15) встречаются импликация → и тождество ≡. В Python их записывают так: A → B — это (not A) or B, A ≡ B — это A == B: ответы двух условий совпадают.

Итог

За урок ты научился задавать программе вопросы и собирать из простых ответов сложные. В следующем уроке программа начнёт по этим ответам выбирать, что делать. Вот что понадобится дальше.

  • Сравнения== != < > <= >= дают True или False — значения типа bool. = присваивает, == сравнивает.
  • and, or, notОба; хотя бы одно, в том числе оба; наоборот. «Ровно одно» — a != b.
  • ПорядокСравнения, not, and, or. Сомневаешься — ставь скобки.
  • Интервал5 <= x < 20 — то же, что 5 <= x and x < 20.
  • Короткое вычислениеПравая часть не вычисляется, если ответ уже известен: проверка, которая защищает от ошибки, — первой.
  • ИстинностьЛожны 0, пустая строка, None и False. Пиши x == 2 or x == 3, а не x == 2 or 3.
  • Отрицаниеnot (a and b) — not a or not b; not (a or b) — not a and not b.
  • → и ≡A → B — (not A) or B; A ≡ B — A == B.

Проверьте себя

Ответь сначала сам, потом открой ответ.

Вопрос 1

Что напечатает print(7 >= 7, 7 > 7)?

ОтветСкрыть ответ
Ответ

True False: >= включает равенство, > — нет.

Вопрос 2

Программа из двух строк x = input() и print(x == 5). Что она напечатает, если ввести 5? Почему?

ОтветСкрыть ответ
Ответ

False: input вернул строку "5", а строка не равна числу. Нужно int(input()) == 5.

Вопрос 3

Чему равно True or False and False?

ОтветСкрыть ответ
Ответ

True: and выполняется раньше — False and False даёт False, затем True or False — True.

Вопрос 4

Пусть x = 0. Что случится при print(10 / x > 2 and x != 0)?

ОтветСкрыть ответ
Ответ

ZeroDivisionError: левая часть вычисляется первой, а в ней деление на ноль. Проверку x != 0 нужно поставить слева.

Вопрос 5

Что напечатает print(x == 1 or 2) при x = 5? Как записать условие «x равно 1 или 2» правильно?

ОтветСкрыть ответ
Ответ

2: левая часть ложна, и or отдаёт правую — число 2. Верно: x == 1 or x == 2.

Практика

Для проверки ответов нужен JavaScript. Условия, подсказки и решения доступны ниже.

Условие «делится на 3 или на 5, но не на оба сразу»

Запиши условие «n делится на 3 или на 5, но не на оба сразу». Проверь его, подставляя по очереди n = 9, 10, 7 и 15: для каждого числа программа печатает True или False.

Запишите четыре значения через пробел в порядке чисел: 9, 10, 7, 15.

Что напечатает программа?

print(7 > 3 and 2 > 5)print(7 > 3 or 2 > 5)print(not 7 > 3)

Запишите напечатанные строки через пробел в порядке вывода.

Что напечатает программа?

print(0 and 10 / 0)

Запишите напечатанное значение.

Что напечатает программа?

print(bool(""))print(bool("0"))print(bool(0))print(bool(" "))

Запишите напечатанные строки через пробел в порядке вывода.

Импликация A → B для трёх чисел

Пусть A — «n больше 10», B — «n чётное». Чему равна импликация A → B, то есть (not A) or B, при n = 7, 12 и 15?

Запишите три значения через пробел в порядке n: 7, 12, 15.

Условие високосного года

Год високосный, если делится на 4 и не делится на 100 или если делится на 400. Запиши условие для y и проверь его, подставляя по очереди 1900, 2000, 2024 и 2023.

Запишите четыре значения через пробел в порядке лет: 1900, 2000, 2024, 2023.