2.11. Условные операторы

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

n = 42

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

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

Блок-схема, показывающая if/elif/else: два ромбовидных решающих узла с их телами, переходящих к завершающему телу else, когда обе проверки ложны.

Когда-либо выполняется только одна ветвь. Проверки вычисляются сверху вниз, пока одна не пройдёт успешно; остальные пропускаются.

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

Обе формы используют сокращённое вычисление, поэтому дорогостоящая проверка справа выполняется только тогда, когда более дешёвые проверки слева ещё не решили вопрос.