2.11. Умовні оператори¶
Умовний оператор виконує блок коду лише тоді, коли певна умова є істинною. Ключове слово — if, за яким необов’язково можуть іти одна або кілька гілок elif («else if») і фінальне else.
n = 42
if n > 0:
print("positive")
elif n < 0:
print("negative")
else:
print("zero")
Тіло кожної гілки — це все, що написано з відступом під нею (за угодою, чотири пробіли). Python обходить гілки по порядку, виконує першу, чия умова є істинною, і пропускає решту. Блок else виконується лише якщо всі попередні умови були хибними; він завжди є необов’язковим.
Виконується лише одна гілка. Умови перевіряються зверху вниз до першої успішної; решта пропускаються.¶
2.11.1. Хибність та істинність¶
Умова в if не обов’язково має повертати True або False — будь-яке значення вважається або хибним, або істинним. Хибні значення:
Все інше є істинним. Це дозволяє писати компактні умови:
if name: # false on empty string
print("hello", name)
if items: # false on empty list, dict, etc.
process(items)
Зверніть увагу: хибність змінює сенс. if value: не є тим самим, що if value is not None: — перший вираз також є хибним, коли value дорівнює 0 або "". Коли ви дійсно маєте на увазі «чи є це рівно None», явно використовуйте is None / is not None.
2.11.2. Тернарні вирази¶
Умова може з’являтися всередині виразу:
label = "even" if n % 2 == 0 else "odd"
Читається як «label є "even" якщо n % 2 == 0 інакше "odd".» Зручно для однорядників; для всього, що займає більше одного рядка, повний оператор if читається краще.
2.11.3. Вкладення та ранні повернення¶
Умовні оператори можуть вкладатися на будь-яку глибину, але кожен додатковий рівень відступу ускладнює читання функції. Наведений нижче приклад перевіряє чотири умови перед виконанням основної роботи і залишає корисний рядок похованим на чотирьох рівнях відступу:
def process(item):
if item is not None:
if item.is_valid():
if item.size() > 0:
if item.owner == "me":
return do_the_work(item)
return None
Два шаблони спрощують такий код.
2.11.3.1. Ранні повернення для перевірки передумов¶
Обробіть кожен «аварійний» випадок спочатку — кожен зі своїм return — щоб основна логіка залишалася на зовнішньому рівні відступу. Кожна перевірка читається як «цей випадок ми не обробляємо; виходимо»:
def process(item):
if item is None:
return None
if not item.is_valid():
return None
if item.size() == 0:
return None
if item.owner != "me":
return None
return do_the_work(item)
«Основний шлях» тепер є одним рядком унизу функції, а не похованим всередині чотирьох рівнів. Цей стиль іноді називають шаблоном сторожового умови (guard clause).
2.11.3.2. Комбінування умов за допомогою and / or¶
Коли кілька умов мають виконуватися разом для однієї гілки, об’єднуйте їх за допомогою and, а не вкладень. Умови, кожна з яких незалежно запускає гілку, об’єднуються за допомогою or:
# all must hold -- use `and`
if user.is_admin() and user.has_permission("write") and not locked:
save()
# any one of them is enough -- use `or`
if c == " " or c == "\t" or c == "\n":
whitespace_count += 1
Обидві форми є короткозамкненими: дорогий виклик справа виконується лише тоді, коли дешевші перевірки зліва вже не вирішили питання.