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
Обе формы используют сокращённое вычисление, поэтому дорогостоящая проверка справа выполняется только тогда, когда более дешёвые проверки слева ещё не решили вопрос.