if — оператор розгалуження
Порядок дій алгоритму може бути нелінійним. Іноді потрібно обрати з двох і більше варіантів гілок алгоритму.
Оператор розгалуження if
дозволяє обрати одну з гілок алгоритму на підставі виконання або невиконання заданої умови.
Загальний випадок запису
У загальному випадку оператор розгалуження if
записується наступним чином:
if <умова>:
<блок коду № 1, якщо умова == True>
else:
<блок коду № 2, якщо умова == False>
<наступні оператори>
Як інтерпретатор Python обробляє оператор розгалуження if
?
- На першому кроці обчислюється значення виразу
<умова>
. - Якщо результат обчислення дорівнює
True
, то виконається блок коду № 1, який слідує одразу після рядкаif <умова>:
- Якщо результат обчислення дорівнює
False
, то виконається блок коду № 2, який слідує одразу після рядкаelse:
. - Після виконання блоку № 1 або блоку № 2 будуть виконані наступні оператори.
digraph VotingEligibility {
node [shape=box fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
edge [fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
start [label="попередні оператори"];
check [shape=diamond label="умова"];
allow [label="блок коду № 1"];
deny [label="блок коду № 2"];
end [label="наступні оператори"];
start -> check;
check -> allow [label="True"];
check -> deny [label="False"];
allow -> end;
deny -> end;
}
⚠️ Важливо: в операторі if
виконається або блок коду № 1, або блок коду № 2, але не обидва одразу! Не існує такої умови, щоб виконувались обидва блоки.
Іноді можна зустріти таку форму, коли немає другого блоку коду:
if <умова>:
<блок коду № 1, якщо умова == True>
<наступні оператори>
У цьому випадку, якщо результат обчислення виразу <умова>
дорівнює False
, то будуть виконані одразу <наступні оператори>
:
digraph VotingEligibility {
node [shape=box fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
edge [fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
start [label="попередні оператори"];
check [shape=diamond label="умова"];
allow [label="блок коду № 1"];
end [label="наступні оператори"];
start -> check;
check -> allow [label="True"];
check -> end [label="False"];
allow -> end;
}
На місці виразу <умова>
може бути:
- константи
False
абоTrue
if True:
if False:
- імена змінних булевого типу
if not_found:
- вирази рівності або нерівності, порівняння чисел, рядків, списків:
==
,!=
,>
,<
,<=
,>=
:if count == 0
if sum != 100
if age >= 18
if name == "John"
- входження елемента в послідовність:
in
if student_name in list_of_best_students:
- складені вирази з операторами
or
,and
:if radius > 0 and distance > 0
- виклики різних функцій або методів:
if get_deсision()
if some_object.some_method()
- або комбінації вищезгаданих прикладів за допомогою операторів
or
,and
,not
.
У прикладі нижче, програма запитує вік користувача, і залежно від умови age >= 18
:
age = int(input("Вік: "))
if age >= 18:
print("Можна голосувати")
else:
print('Не можна голосувати')
digraph VotingEligibility {
node [shape=box fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
edge [fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
start [shape=oval label="Початок"];
input [shape=parallelogram label="age"];
check [shape=diamond label="age >= 18"];
allow [shape=parallelogram label="Можна голосувати"];
deny [shape=parallelogram label="Не можна голосувати"];
end [shape=oval label="Кінець"];
start -> input;
input -> check;
check -> allow [label="True"];
check -> deny [label="False"];
allow -> end;
deny -> end;
}
Іноді бувають більш складні розгалуження, коли потрібно обрати не два альтернативних шляхи, а більше.
age: int = int(input("Вік: "))
if age <= 5:
# 1, 2, 3, 4, 5
print("Дитячий садок")
elif age <= 16:
# 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
print("Школа")
elif age <= 21:
# 17, 18, 19, 20, 21
print("Університет")
else:
# 22 і більше
print("Доросле життя")
Блок-схема алгоритму для цього прикладу показана на рисунку нижче:
digraph CFG {
node [shape=box fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
edge [fontname="Helvetica" fontsize="12" color="#87D0F5" penwidth=2];
start [shape=oval label="Початок"];
input_age [shape=parallelogram label="age"];
cond1 [shape=diamond label="age <= 5"];
print_kindergarten [shape=parallelogram label="Дитячий садок"];
cond2 [shape=diamond label="age <= 16"];
print_school [shape=parallelogram label="Школа"];
cond3 [shape=diamond label="age <= 21"];
print_university [shape=parallelogram label="Університет"];
print_adult [shape=parallelogram label="Доросле життя"];
end [shape=oval label="Кінець"];
start -> input_age;
input_age -> cond1;
cond1 -> print_kindergarten [label="True"];
cond1 -> cond2 [label="False"];
print_kindergarten -> end;
cond2 -> print_school [label="True"];
cond2 -> cond3 [label="False"];
print_school -> end;
cond3 -> print_university [label="True"];
cond3 -> print_adult [label="False"];
print_university -> end;
print_adult -> end;
}
Ледаче обчислення умов
У Python умовні вирази в операторі if
виконуються за принципом ледачого обчислення (lazy evaluation), коли використовується логічні оператори and
та or
. Це означає, що Python припиняє перевірку умов щойно результат стає відомим. Наприклад, у виразі if a and b:
значення b
не буде обчислено, якщо a
вже є False
, адже вся умова не може бути True
. Аналогічно, у виразі if a or b:
, якщо a
є True
, Python не перевірятиме b
. Це дозволяє уникнути зайвих обчислень і, що важливо, може запобігти помилкам — наприклад, якщо друга умова викликає функцію, яка не має сенсу, якщо перша не виконалась. Така поведінка часто використовується для безпечного доступу до об’єктів, які можуть бути None
.
Уявіть, що ви питаєте друга:
— Чи ми йдемо гуляти, якщо зараз не дощить і у тебе є настрій?
Якщо він каже: «Йде дощ» — ви навіть не будете питати про настрій. Це і є ледаче обчислення: немає сенсу перевіряти другу умову, якщо перша вже дає відповідь.
Ось приклади, які демонструють ледаче обчислення умов в операторі if
у Python:
✅ Позитивний приклад:
user = None
# Тут перевірка user is not None відбувається першою
# Якщо user — None, то друга частина не буде виконуватись
if user is not None and user.is_active():
print("Користувач активний")
У цьому прикладі, якщо user
є None
, то виклик user.is_active()
не буде виконано, що запобігає помилці AttributeError
.
❌ Негативний приклад (без ледачого обчислення)
user = None
# Тут Python намагається обчислити обидві частини одразу
# Це призведе до помилки, бо user — None
if user.is_active() and user is not None:
print("Користувач активний")
У цьому випадку виникне помилка AttributeError
, оскільки user.is_active()
викликається до перевірки user is not None
.
Приведення різних об'єктів до bool
Оператор if
очікує, що значення <умова>
буде булевого типу (bool
). Не завжди програмісти утруднюють себе написанням коректного коду і підставляють у <умова>
значення відмінного від bool
типу. У цьому випадку інтерпретатор Python робить неявне приведення типів до bool
.
У прикладі нижче value — посилається на об'єкт типу str
(рядок). При цьому ж value
використовується як умова в операторі if
. Тут інтерпретатор буде неявно приводити значення value
(рядковий тип) до булевого типу (bool
)
value: str = input("Введіть ім'я:")
if value:
print("Добрий день", value)
else:
print("Ви ввели порожній рядок")
У таблиці нижче показані різні не-булеві значення, а також коректний запис для використання в умовному операторі if
:
Значення value | Пояснення | Очікуване | Коректний запис |
---|---|---|---|
0 |
нуль цілочисельний | False |
value == 0 |
0.0 |
нуль дійсний | False |
value == 0.0 |
[] |
порожній список | False |
len(value) == 0 |
{} |
порожній словник | False |
len(value) == 0 |
() |
порожній кортеж | False |
len(value) == 0 |
"" |
порожній рядок | False |
len(value) == 0 |
None |
об'єкт None | False |
value is None |
⚠️ Увага! Неявне приведення типів в умові оператора if
— поганий тон! Уникайте неявного приведення типів!