Python Core

Логіка та розгалуження

Порівняння та ланцюжки порівнянь, логічні оператори and, or, not з коротким замиканням, істинність значень, розгалуження if, elif, else, умовний вираз та інструкція match.

Логіка та розгалуження

Програма, що приймає рішення

До цього уроку програма виконувала рядки один за одним, завжди в одному порядку. Реальні програми реагують на дані: перевіряють пароль, визначають оцінку, обирають дію. Для цього потрібні умови: вирази, результат яких True або False, і розгалуження, яке за умовою вибирає, який код виконувати.

🎯 Мета лекції

  • Записувати умови з операторами порівняння й ланцюжками.
  • Поєднувати умови через and, or, not і знати про коротке замикання.
  • Пояснювати, що значення можуть бути «істинними» чи «хибними».
  • Писати розгалуження if, elif, else і умовний вираз.
  • Використовувати match для вибору за шаблоном.

🔑 Ключові терміни

  • Умова (condition): вираз, який перевіряють на істинність.
  • Розгалуження (branching): вибір коду за умовою.
  • Блок (block): група рядків із відступом.
  • Коротке замикання (short-circuit): зупинка обчислення, коли результат уже відомий.
  • Істинність (truthiness): чи вважає Python значення істинним.

Пригадаємо попередній урок

Порівняння

Оператори порівняння дають результат типу bool: True або False.

ОператорЗначенняПрикладРезультат
==дорівнює5 == 5.0True
!=не дорівнює5 != 4True
<менше3 < 2False
>більше3 > 2True
<=менше або дорівнює3 <= 3True
>=більше або дорівнює2 >= 3False

Числа різних типів порівнюються за значенням: 5 == 5.0 дає True. Порівняти число з рядком за порядком не можна:

print(5 > "3")
TypeError: '>' not supported between instances of 'int' and 'str'

Рядки порівнюються за кодами символів, посимвольно зліва направо. Тому результат не завжди збігається з людською інтуїцією:

print("apple" < "banana", "Ab" < "ab", "10" < "9", 10 < 9)
True True True False

Великі літери мають менші коди, ніж малі, а "10" менше за "9", бо перший символ "1" менший за "9". Для чисел у рядках спершу використовують int().

Ланцюжки порівнянь

Python дозволяє записати подвійну умову як у математиці:

x = 7
print(0 < x < 10)
print(0 < x < 5)
True
False

Запис 0 < x < 10 означає 0 < x and x < 10, причому x обчислюється один раз.

Не плутайте = та ==. Один знак дорівнює присвоює значення, два — порівнюють. Дробові числа через == порівнювати не слід (урок про типи): 0.1 + 0.2 == 0.3 дає False.

Логічні оператори

Умови об'єднують трьома операторами:

ОператорЗначенняПриклад
andобидві умови істинніx > 0 and x < 10
orхоча б одна істиннаx < 0 or x > 10
notзапереченняnot x > 5
print(True and False, True or False, not True)
False True False

Пріоритет: not вищий за and, а and вищий за or. Вираз 1 == 2 or 3 == 3 and 4 == 4 обчислюється як 1 == 2 or (3 == 3 and 4 == 4) і дає True. Для читабельності складні умови беруть у дужки.

Перевірка належності через in:

print("a" in "abc", "z" not in "abc", 3 in [1, 2, 3])
True True True

Коротке замикання

Python обчислює and та or зліва направо і зупиняється, щойно результат відомий:

  • A and B: якщо A хибне, результат уже відомий, B не обчислюється;
  • A or B: якщо A істинне, результат відомий, B не обчислюється.
def f():
    print("f викликана")
    return 1

print(0 and f())
print(1 and f())
print(1 or f())
print(0 or f())
0
f викликана
1
1
f викликана
1

Це корисно для захисту від помилок: у виразі n != 0 and 10 / n > 1 ділення виконується, лише якщо n не нуль.

and і or повертають операнд

Важлива особливість Python: and і or повертають не True чи False, а один зі своїх операндів:

  • A or B повертає A, якщо A істинне, інакше B;
  • A and B повертає A, якщо A хибне, інакше B.
print(0 or "default", "" or "Гість", "a" or "b")
print(5 and 7, 0 and 7)
default Гість a
7 0

Тому name or "Гість" — поширений спосіб задати значення за замовчуванням. Простежте це в трасувальнику:

and, or і операнди
Завантаження трасування…

Після рядка shown = name or "Гість" змінна shown вказує на об'єкт 'Гість', бо порожній рядок хибний. Рядок count and 10 / count не викликає ділення на нуль: count дорівнює 0, тож and повертає його одразу.

Істинність значень

Умову можна записати не лише як порівняння: будь-яке значення Python вважає істинним або хибним. Хибні такі значення:

ЗначенняТип
Falsebool
0, 0.0int, float
""порожній рядок
[], (), {}, set()порожні колекції
NoneNoneType

Усі інші значення істинні. Функція bool() показує це:

print(bool(0), bool(0.0), bool(""), bool([]), bool(None))
print(bool("0"), bool([0]), bool(-1))
False False False False False
True True True

Рядок "0" і список [0] не порожні, тому істинні. Завдяки цьому можна писати if name: замість if name != "":.

Розгалуження if, elif, else

Інструкція if виконує блок коду, лише якщо умова істинна:

age = 17
if age >= 18:
    print("Доступ дозволено")
else:
    print("Доступ заборонено")
Доступ заборонено

Синтаксис має три обов'язкові елементи:

  1. після умови стоїть двокрапка :;
  2. рядки блоку мають відступ (4 пробіли), і лише відступ показує, що рядок належить блоку;
  3. else не має умови: він виконується, коли жодна умова вище не спрацювала.

Щоб перевірити кілька варіантів, між if і else ставлять elif (від else if):

score = 82
if score >= 90:
    grade = "A"
elif score >= 75:
    grade = "B"
elif score >= 60:
    grade = "C"
else:
    grade = "F"
print(grade)
B

Python перевіряє умови зверху вниз і виконує перший блок, умова якого істинна. Решта пропускаються, навіть якщо їхні умови теж були б істинними. Бал 82 задовольняє і >= 75, і >= 60, але виконується лише B.

Вибір галузі elif
Завантаження трасування…

У трасувальнику видно, що рядок grade = "A" пропущений, а після перевірки score >= 75 виконується grade = "B".

Кілька окремих if поспіль — це незалежні перевірки, а if + elif — одна перевірка, у якій спрацює лише одна галузь. Для x = 5 код if x > 3: ... і if x > 1: ... виведе обидві галузі, а з elif — лише першу.

Вкладені умови та pass

Блок може містити інші if. Кожен рівень вкладеності додає відступ:

age = 20
has_ticket = True
if age >= 18:
    if has_ticket:
        print("Прохід дозволено")
    else:
        print("Потрібен квиток")
Прохід дозволено

Глибоку вкладеність краще замінювати об'єднанням умов: if age >= 18 and has_ticket:. Порожній блок записують словом pass (інструкція, що нічого не робить).

Умовний вираз

Коли потрібно вибрати між двома значеннями, зручний умовний вираз (conditional expression):

age = 17
status = "дорослий" if age >= 18 else "неповнолітній"
print(status)
неповнолітній

Форма: значення_якщо_істина if умова else значення_якщо_хиба. Це вираз, тому його можна підставити будь-де, де потрібне значення.

Типові помилки синтаксису

= замість ==

x = 5
if x = 5:
    print(1)
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Відсутня двокрапка

if x == 1
    print(1)
SyntaxError: expected ':'

Помилки відступів

Блок без відступу:

if True:
print(1)
IndentationError: expected an indented block after 'if' statement on line 1

Нерівний відступ:

if True:
    print(1)
  print(2)
IndentationError: unindent does not match any outer indentation level

Редактор зазвичай ставить відступ автоматично, а для переходів на новий рівень використовують клавішу Tab. Змішувати пробіли й табуляцію в одному файлі не слід.

match: вибір за шаблоном

Коли одне й те саме значення порівнюють з багатьма варіантами, ланцюжок elif повторює порівняння знову й знову:

command = "stop"
if command == "go":
    print("їдемо")
elif command == "stop" or command == "halt":
    print("зупиняємось")
elif command == "back":
    print("назад")
else:
    print("невідома команда")
зупиняємось

Для таких випадків у Python є інструкція match. Вона бере одне значення й порівнює його зі шаблонами (patterns) по черзі. Розглянемо її поступово, від найпростішого до складнішого.

Простий match

Той самий приклад із match:

command = "stop"
match command:
    case "go":
        print("їдемо")
    case "stop" | "halt":
        print("зупиняємось")
    case "back":
        print("назад")
    case _:
        print("невідома команда")
зупиняємось

Будова інструкції:

  • match command: — значення, яке перевіряємо, і двокрапка;
  • кожен case шаблон: — один варіант, після нього блок з відступом;
  • Python порівнює значення з шаблонами зверху вниз і виконує блок першого збігу; решта пропускаються;
  • шаблон _ (підкреслення) збігається з будь-яким значенням, тому його ставлять останнім як «усе інше» (аналог else).

Простежте виконання в трасувальнику:

Вибір за шаблоном
Завантаження трасування…

Шаблон "go" не збігся, шаблон "stop" | "halt" збігся, тому виконано лише його блок, а case _ пропущено.

Що буде, якщо збігу немає

Блок case _ не обов'язковий. Якщо жоден шаблон не підійшов, match нічого не робить, і програма йде далі:

day = 3
match day:
    case 1:
        print("понеділок")
    case 6:
        print("субота")
print("після match")
після match

Для day = 6 вивід був би субота, а потім після match.

Кілька значень в одному case

Знак | читається як «або». Він об'єднує кілька шаблонів в один блок:

for d in (1, 5, 6, 7):
    match d:
        case 6 | 7:
            print(d, "вихідний")
        case _:
            print(d, "робочий")
1 робочий
5 робочий
6 вихідний
7 вихідний

Це коротше за if d == 6 or d == 7:.

Захоплення значення

Шаблон може бути ім'ям. Тоді він збігається з будь-яким значенням і записує його в цю змінну:

point = 42
match point:
    case 0:
        print("нуль")
    case n:
        print("число", n)
число 42

Тут n — не порівняння з наявною змінною, а нова змінна, яку створює шаблон. Відмінність від _: підкреслення значення не зберігає, а ім'я зберігає.

Оскільки ім'я збігається з усім, шаблон з голим іменем має бути останнім. Інакше Python відхиляє код:

match 5:
    case x:
        print(x)
    case 1:
        print(1)
SyntaxError: name capture 'x' makes remaining patterns unreachable

Додаткова умова (guard)

Після шаблону можна дописати if з умовою. Блок виконається, лише якщо шаблон збігся і умова істинна:

for t in (-5, 0, 20, 35):
    match t:
        case n if n < 0:
            print(n, "мороз")
        case 0:
            print(n, "нуль")
        case n if n <= 25:
            print(n, "тепло")
        case _:
            print(t, "спека")
-5 мороз
0 нуль
20 тепло
35 спека

Ім'я n захоплює значення, а if перевіряє його. Якщо умова хибна, Python переходить до наступного case.

Шаблони для кортежів

Кортеж (tuple) — впорядкований набір значень у круглих дужках, наприклад ("move", 3). Докладно кортежі розглянемо в уроці про колекції. Тут вони потрібні, бо match уміє порівнювати структуру значення і витягувати з неї частини.

Команда складається з назви й, можливо, параметрів. Шаблон описує форму кортежу:

for cmd in (("stop",), ("move", 3), ("move", 3, 4), ("jump",)):
    match cmd:
        case ("stop",):
            print(cmd, "стоп")
        case ("move", steps):
            print(cmd, "крок", steps)
        case ("move", x, y):
            print(cmd, "до точки", x, y)
        case _:
            print(cmd, "невідома команда")
('stop',) стоп
('move', 3) крок 3
('move', 3, 4) до точки 3 4
('jump',) невідома команда

Правила:

  • літерали ("move") мають збігтися точно;
  • імена (steps, x, y) захоплюють відповідні елементи;
  • кількість елементів теж має збігтися: ("move", steps) не підходить для кортежу з трьох значень, тому для нього спрацював третій case.

Ще один приклад: положення точки на площині.

point = (3, 0)
match point:
    case (0, 0):
        print("початок координат")
    case (x, 0):
        print("на осі X, x =", x)
    case (0, y):
        print("на осі Y, y =", y)
    case (x, y):
        print("точка", x, y)
на осі X, x = 3

Шаблони перевіряються по черзі: (0, 0) не збігся, а (x, 0) збігся, бо другий елемент дорівнює нулю, а перший захоплено в x.

Перевірка типу

Шаблон тип() збігається, якщо значення має цей тип. Дужки обов'язкові:

for v in (7, 3.5, "текст", True, None):
    match v:
        case bool():
            print(repr(v), "логічне")
        case int():
            print(repr(v), "ціле")
        case float():
            print(repr(v), "дробове")
        case str():
            print(repr(v), "рядок")
        case None:
            print(repr(v), "None")
7 ціле
3.5 дробове
'текст' рядок
True логічне
None None

Порядок важливий: bool — підтип int (урок про типи), тому True збігся б і з int(). Тому bool() стоїть перед int(). Шаблон None пишеться без дужок: це літерал.

Тип можна поєднати з іменем через as усередині структури:

match ("move", 5):
    case ("move", int() as steps):
        print("кроків:", steps)
кроків: 5

Пастка: ім'я в case не порівнюється зі змінною

Найпоширеніша помилка: спроба порівняти значення зі змінною через case ім'я. Python сприймає ім'я як шаблон захоплення, а не як порівняння:

RED = 1
color = 2
match color:
    case RED:
        print("RED тепер дорівнює", RED)
RED тепер дорівнює 2

Хоча color не дорівнює 1, блок виконався, а змінну RED перезаписано. Порівнювати зі змінною в case напряму не можна: використовують літерали або умову case n if n == RED.

Приклад: калькулятор

Об'єднаємо введення, перетворення та match:

a = float(input("a: "))
b = float(input("b: "))
op = input("Операція (+ - * /): ")
match op:
    case "+":
        print(a + b)
    case "-":
        print(a - b)
    case "*":
        print(a * b)
    case "/":
        print(a / b)
    case _:
        print("невідома операція")
python calc.py
a: 8
b: 2
Операція (+ - * /): /
4.0

Коли що вибирати

СитуаціяІнструмент
Умова з діапазонами й порівняннями (score >= 75)if / elif
Складна логіка з and, or, notif / elif
Одне значення проти кількох точних варіантівmatch
Потрібно розібрати структуру (кортеж, тип) і витягти частиниmatch
Помилки синтаксису в match схожі на помилки в if: пропущена двокрапка дає SyntaxError: expected ':', а case без відступу — IndentationError: expected an indented block after 'match' statement on line 2. Альтернативи, що прив'язують різні імена (case (a, b) | (a,):), заборонені: SyntaxError: alternative patterns bind different names.

Підсумок

  1. Порівняння (==, !=, <, >, <=, >=) дають bool. Ланцюжок 0 < x < 10 — дві перевірки разом.
  2. and, or, not об'єднують умови. Пріоритет: not, and, or.
  3. and та or зупиняються, коли результат відомий, і повертають один з операндів.
  4. Хибні значення: False, 0, 0.0, "", порожні колекції, None. Решта істинні.
  5. if / elif / else перевіряють умови зверху вниз і виконують перший істинний блок. Блок позначає відступ.
  6. a if умова else b — умовний вираз.
  7. match порівнює значення з шаблонами по черзі: літерали, |, імена-захоплення, умова if, кортежі, типи. _ означає «усе інше».

Типові хибні уявлення

Передбачте, перш ніж запускати

Практичні завдання

Наступний урок: цикли та ітерація. while, for, range, break і continue.
Copyright © 2026