2.11. Умовні оператори

Умовний оператор виконує блок коду лише тоді, коли певна умова є істинною. Ключове слово — if, за яким необов’язково можуть іти одна або кілька гілок elif («else if») і фінальне else.

n = 42

if n > 0:
    print("positive")
elif n < 0:
    print("negative")
else:
    print("zero")

Тіло кожної гілки — це все, що написано з відступом під нею (за угодою, чотири пробіли). Python обходить гілки по порядку, виконує першу, чия умова є істинною, і пропускає решту. Блок else виконується лише якщо всі попередні умови були хибними; він завжди є необов’язковим.

A flowchart showing if/elif/else: two diamond decision tests with their bodies, falling through to a final else body when both tests are false.

Виконується лише одна гілка. Умови перевіряються зверху вниз до першої успішної; решта пропускаються.

2.11.1. Хибність та істинність

Умова в if не обов’язково має повертати True або False — будь-яке значення вважається або хибним, або істинним. Хибні значення:

  • False і None

  • Числовий нуль: 0, 0.0

  • Порожні послідовності та колекції: "", [], (), {}, b""

Все інше є істинним. Це дозволяє писати компактні умови:

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

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