Модуль 2 · Условия

Справочник по Python · модуль 2 · условия

Глава 2.2

2.2

Составление условий
без ветвления

В этой главе разобрано, как записать на Python словесные условия задачи: «все три», «хотя бы одно», «ровно одно», «ни одного». Оператор if здесь не используется: программа вычисляет выражение и выводит результат.

Категория
Синтаксис и базовые концепции
Уровень
Начальный
Связанные темы
Логический тип, ветвление, операции деления
Зачем это знать
Переводить словесное условие задачи в выражение на Python

§1Три формулировки условий

Условия в задачах формулируют словами. Чаще всего встречается одна из трёх формулировок.

ФормулировкаСмыслЧем записывается
Каждое — «все три числа кратны трём»истинны все условия без исключенияand
Хотя бы одно — «среди чисел есть отрицательное»истинно одно или большеor
Только одно — «одно число чётное, другое нет»истинно ровно одно, остальные ложныand и or вместе

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

§2Простая проверка: делимость

В примерах этой главы часто встречается проверка делимости. Выражение A % 3 == 0 проверяет, делится ли A на три без остатка.

В нём две части: A % 3 — остаток от деления (глава 1.8), == 0 — сравнение этого остатка с нулём. Если остаток равен нулю, число делится нацело, и выражение даёт True.

Pythonбазовые проверки
A % 2 == 0    # A чётное
A % 2 != 0    # A нечётное
A % 3 == 0    # A кратно трём
A < 0          # A отрицательное

Каждая такая строка даёт логическое значение. Составное условие состоит из простых проверок, соединённых операторами. Читать его удобно в том же порядке: сначала определить, что проверяет каждая часть, затем — как части соединены.

§3Каждое — оператор and

Задача: проверить, что числа A, B и C кратны трём. Слово «и» между требованиями означает and.

Pythonусловие «каждое»
(A % 3 == 0) and (B % 3 == 0) and (C % 3 == 0)

Операторов and в выражении может быть несколько. Выражение истинно, только если истинны все его части. Если хотя бы одно число не делится на три, результат — False.

main.pyпроверка на живых числах
A, B, C = 9, 6, 3

print((A % 3 == 0) and (B % 3 == 0) and (C % 3 == 0))   # True

Скобки вокруг каждой проверки не обязательны: сравнение == выполняется раньше and. В длинных условиях скобки всё же ставят: по ним видно, что выражение состоит из трёх отдельных проверок.

На полях: and прекращает проверку на первом False

Python вычисляет составное условие слева направо и останавливается, когда результат уже определён. В цепочке and первое ложное условие делает ложным всё выражение, и остальные проверки не выполняются. Это правило языка, поэтому слева обычно ставят проверку, которая чаще оказывается ложной.

§4Хотя бы одно — оператор or

Задача: проверить, есть ли среди чисел A, B, C отрицательное. Достаточно одного отрицательного числа, поэтому нужен or.

main.pyусловие «хотя бы одно»
A = -5
B = 10
C = 3

print((A < 0) or (B < 0) or (C < 0))
Вывод в терминалрезультат запуска
True

Результат истинный, потому что A меньше нуля. Значения B и C на него уже не влияют: оператору or достаточно одной истинной части. Выражение ложно, только когда ложны все три проверки.

§5Только одно — комбинация

Задача: проверить, что из двух чисел одно чётное, а другое нечётное — то есть ровно одно чётное.

Одним оператором это условие не записать. Перечислим случаи, в которых оно выполнено:

  1. A чётное и B нечётное — записывается как A % 2 == 0 and B % 2 != 0;
  2. A нечётное и B чётное — записывается как A % 2 != 0 and B % 2 == 0;
  3. подходит любой из двух случаев, поэтому они соединяются через or.
Pythonусловие «только одно»
(A % 2 == 0 and B % 2 != 0) or (A % 2 != 0 and B % 2 == 0)
main.pyпроверяем
A, B = 4, 7

print((A % 2 == 0 and B % 2 != 0) or (A % 2 != 0 and B % 2 == 0))   # True

Число 4 чётное, число 7 нечётное: истинна первая часть условия, и оператору or этого достаточно. Если оба числа чётные, обе части ложны и результат — False. Этим «ровно одно» отличается от «хотя бы одно»: когда чётны оба числа, условие не выполнено.

Скобки показывают, что or соединяет два случая целиком. Приоритет and выше, чем у or, поэтому без скобок результат тот же, но в выражении такой длины их ставят, чтобы порядок вычисления был виден.

§6Ни одного и не все

Ещё две частые формулировки получаются из разобранных с помощью not.

ФормулировкаКак записатьЧерез что получается
ни одно из чисел не отрицательноnot (A < 0 or B < 0)отрицание «хотя бы одного»
то же самое напрямуюA >= 0 and B >= 0каждое неотрицательно
не все числа кратны трёмnot (A % 3 == 0 and B % 3 == 0)отрицание «каждого»

Первые две строки таблицы описывают одно условие. Отрицание «хотя бы одного» равно «каждое наоборот», а отрицание «каждого» — «хотя бы одно наоборот». Эти правила называются законами де Моргана. При раскрытии скобок после not каждая проверка меняется на противоположную, а and и or меняются местами.

Из двух равносильных записей выбирайте ту, которая ближе к формулировке задачи. Если в условии сказано «оба числа неотрицательны» — пишите A >= 0 and B >= 0. Если «нет ни одного отрицательного» — not (A < 0 or B < 0).

§7Как собирать длинные условия

Условие из четырёх и более проверок трудно читать в одной строке. Его составляют по шагам:

  1. Выпишите словами каждое требование задачи отдельной строкой.
  2. Запишите каждое требование простой проверкой, как в §2.
  3. Определите связку: «и» между всеми — and, «или» — or, «ровно одно» — комбинация.
  4. Дайте промежуточным проверкам имена, если их больше трёх.

Сравните две записи одного условия — «человек совершеннолетний, со стажем и без задолженностей»:

Pythonодной строкой
print(age >= 18 and experience >= 3 and debt == 0)
Pythonс промежуточными именами
is_adult = age >= 18
is_experienced = experience >= 3
has_no_debt = debt == 0

print(is_adult and is_experienced and has_no_debt)

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

§8Частые ошибки

Что написаноЧто произойдётКак правильно
A % 2 == 0 or B % 2 == 0 для «ровно одного»условие истинно и когда оба числа чётныеразвернуть в два случая через and и соединить их or
A and B < 0проверяется другое условие: A считается истиной при любом ненулевом значенииA < 0 and B < 0 — у каждой проверки своя левая часть
A % 2 = 0SyntaxError — присваивание вместо сравненияA % 2 == 0
A or B or C < 0 для «есть отрицательное»результат почти всегда True — сравнение относится только к CA < 0 or B < 0 or C < 0
not A < 0 or B < 0not применился только к первой проверке — приоритет выше ornot (A < 0 or B < 0)
A % 2 == 0 and != 0SyntaxError — у второго сравнения нет операндаповторить проверяемое значение полностью
Сравнение записано только у одного числа

Строка A or B or C < 0 повторяет русскую фразу «A или B или C меньше нуля». Python вычисляет её иначе: сначала A как логическое значение, затем B, и только для C выполняется сравнение C < 0. Любое ненулевое число считается истиной (глава 2.1, §3). Программа при этом не останавливается с ошибкой, а выводит неверный результат. Сравнение нужно записать у каждого числа.

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

Как записать условие «все три числа положительны»?

(A > 0) and (B > 0) and (C > 0). Формулировка «все» переводится цепочкой and: достаточно одному числу оказаться неположительным, и результат станет False.

Чем условие «хотя бы одно из двух чётное» отличается от «ровно одно из двух чётное»?

Случаем, когда чётны оба. «Хотя бы одно» — это A % 2 == 0 or B % 2 == 0, и при двух чётных числах оно истинно. «Ровно одно» в этом случае должно давать False, поэтому его собирают из двух взаимоисключающих вариантов через and и or.

Что проверяет выражение A % 5 == 0 and A % 3 == 0?

Что число A делится и на пять, и на три одновременно, то есть кратно пятнадцати. Обе проверки должны быть истинными — этого требует and.

Почему not A < 0 or B < 0 и not (A < 0 or B < 0) — разные условия?

У not приоритет выше, чем у or, поэтому в первой записи отрицание относится только к A < 0: получается «A неотрицательно или B отрицательно». Во второй записи скобки задают другой порядок: сначала вычисляется всё условие, затем отрицание. Смысл — «ни одно из чисел не отрицательно».

Задача для практики: пользователь вводит три числа. Проверьте, что ровно одно из них равно нулю.

Формулировка «ровно одно» разворачивается в три случая — по одному на каждое число, — и в каждом остальные должны быть ненулевыми:

  • (A == 0 and B != 0 and C != 0) or
  • (A != 0 and B == 0 and C != 0) or
  • (A != 0 and B != 0 and C == 0)

Вторая запись короче и опирается на то, что True равно единице: (A == 0) + (B == 0) + (C == 0) == 1. Сумма истинных проверок должна равняться одному.

§10Шпаргалка

Каждое (A > 0) and (B > 0)
Хотя бы одно (A < 0) or (B < 0)
Только одно (A и не B) or (не A и B)
Ни одного not (A < 0 or B < 0)
Простые проверки n % 2 == 0 # чётное n % 3 == 0 # кратно 3 n < 0 # отрицательное
Каждой проверке — свой операнд A < 0 or B < 0 ✓ A or B < 0 ✗

Итог главы

Формулировка «каждое» записывается цепочкой and, «хотя бы одно» — цепочкой or, «только одно» — перечислением подходящих случаев, соединённых or. Любое условие состоит из простых проверок вида A % 2 == 0. Длинное выражение делят на части и каждой дают имя. В главе 2.4 такие условия используются в операторе if.

Глава 2.2 · Составление условий без ветвления · Справочник по Python Автор: Макаров Максим Николаевич