Привет, Хабр! Меня зовут Дмитрий, я аналитик данных и программный эксперт на курсе Python для анализа данных в Яндекс Практикуме. Решил поделиться тем, как реализованы условные операторы в Python: статья поможет вам составить впечатление о Python и улучшит ваше понимание условных операторов, при этом изложенные ниже принципы могут помочь и в других языках программирования и в формулах Excel или гугл-таблиц.
Условные операторы являются ключевым элементом любого языка программирования, так как позволяют выполнять определённые участки кода в зависимости от заданных условий, будь то простые или сложные.
В этой статье мы подробно рассмотрим концепцию условного оператора на примере языка Python. Сначала обсудим основные понятия и термины, такие как условия, функции и объекты. Затем углубимся в изучение условного оператора в Python, его синтаксиса и особенностей применения.
Мы также проанализируем примеры сложных условий и продемонстрируем, как можно упростить код с помощью инверсии. Это сделает ваш код более читаемым и эффективным.
Эта статья будет полезна начинающим программистам, стремящимся улучшить свои навыки работы с условными операторами. Она поможет вам глубже понять эту важную концепцию и научиться применять её на практике.
Простые и сложные условия
Условие может зависеть от переменных и быть сложным. Вот пример: «Чтобы прокатиться на зиплайне через Москву-реку, нужно быть 7 лет или старше, весить меньше 110 килограммов и прийти на аттракцион в светлое время суток». На самом деле условия сложнее, но если эти не выполняются, то на аттракционе делать нечего. Мы можем записать это условие так же, как оно произносится:
(user_age == 7 or user_age > 7) and user_weight < 110 and not night.
Условия в скобках проверяются в первую очередь. Если хотя бы одно условие из стоящих слева и справа от оператора or истинно, то результатом выражения будет истина (True). Так как в Python присвоение значения переменной делается одинарным знаком равно (например, age = 18 поместит в переменную age число 18), то для проверки равенства используется двойное равно ==. Для сравнений «строго больше и строго меньше» используются знаки больше и меньше.
Мы сразу можем упростить выражение в скобках, использовав вместо «строго больше» условие «больше или равно», тогда получится (user_age >= 7) and (user_weight < 110) and (not night). Чтобы оператор and вернул истину, оба выражения и справа, и слева от него должны быть истинны, иначе вернётся ложь (False). Оператор not меняет истину на ложь и наоборот. Если внутри переменной night сейчас хранится False, то not night вернёт True.
Скобки добавлены для того, чтобы выражение было легче читать. Без них порядок действий был бы такой: сначала выполняются все сравнения, потом оператор «не» (not), далее слева направо «и» (and) и только затем «или» (or).
Функции и объекты
Условие может быть настолько сложным, что его нужно проверять отдельной функцией. Функция — это кусочек кода, который выполняется с определёнными вводными (аргументами) и выдаёт результат. В Python функции определяются при помощи ключевого слова def, а вызываются указанием имени функции и аргументов в скобках.
Предположим, что у нас определена функция с именем is_tech_worker, которая возвращает True или False в зависимости от того, считается ли пользователь (user) сотрудником, отвечающим за техническое обслуживание аттракциона:
def is_tech_worker(user):
...
return result
В блоке пропущенного кода (…) могут быть любые операции и сравнения, но внутри функции результат её работы нужно поместить в переменную result, которая и будет возвращена функцией при её вызове. После выполнения оператора return код, расположенный ниже внутри функции, уже не выполняется.
Вызывается функция следующим образом: user_tech_worker = is_tech_worker(user). Тут в функцию передаётся объект user. В Python всё считается объектами, в этом случае это пользовательский тип данных со своими атрибутами.
Ранее мы проверяли вес и рост пользователя, уже сохранённые в отдельные переменные, но, скорее всего, мы также могли использовать атрибуты объекта, в которых хранится возраст и вес: user.age и user.weight. Если в атрибуте объекта хранится либо ложь, либо истина, то мы можем использовать этот атрибут в качестве условия — вместо вызова функции с объектом пользователя в качестве аргумента обращаться к user.tech_worker. Довольно предисловий, теперь мы можем перейти к тому, что такое условный оператор.
Условный оператор в Python
В Python условный оператор — это if. Он позволяет совершить какие-то действия только если условие истинно.
if condition:
do_this()
В Python после if не нужно писать then, вместо этого используются отступы. Мы можем дополнять if последующими elif и else.
if condition:
do_this()
elif second_condition:
do_that()
elif other_condition:
become_busy()
else:
do_nothing()
С отступом после каждого условия даётся своя ветка кода. Выше каждая из них состоит только из вызова одной функции, но каждая ветка может содержать сколько угодно строк.
Во всей конструкции if-elif-else может быть выполнена только одна ветка: если расположенное выше условие истинно, то оставшиеся не проверяются. Для экономии времени выполнения кода условия, которые чаще оказываются истинными, стоит располагать выше. Если мы делаем проверку внутри функции, то полным аналогом кода выше будет такой код:
def check_conditions():
if condition:
return start()
if second_condition:
return do_this()
if other_condition:
return do_that()
return do_nothing()
Мы тут не используем elif и else, так как после return оставшиеся ветки кода выполнены не будут.
Инверсия
Вернёмся к примеру с аттракционом. Если посетитель 14 лет или младше, то поездка на зиплайне проходит с инструктором. Проверяется наличие билета для всех, кроме технических работников. Получается очень много условий. Мы можем разбить их на группы в зависимости от исхода — платная поездка с инструктором, платная поездка без инструктора, бесплатная поездка и поездка не состоялась. Для каждого исхода в одном условном операторе у нас будет своя ветка кода:
if ( user.age >= 7
and user.age <= 14
and user.weight < 110
and user.ticket
and not user.tech_worker):
call_instructor()
validate_ticket(user)
start()
elif (user.age > 14
and user.weight < 110
and user.ticket
and not user.tech_worker):
validate_ticket(user)
start()
elif user.tech_worker:
start()
else:
print('Поездка не состоялась')
У нас очень много условий, поэтому пришлось объединять их в скобки, так как Python позволяет делать перенос строки внутри скобок. Но даже с таким улучшением код сложно читать.
Есть способ сделать код понятнее. В самом конце, если никакие другие ветки кода не выполнены, вступает в действие ветка кода внутри else. В ней мы вызываем функцию print, распечатывающую текст о том, что поездка не состоялась.
Поскольку ветки независимы, у нас много условий дублируется в первой и второй ветке. Для облегчения кода инвертируем условия: если возраст меньше 7 или вес больше либо равен 110, а также нет билета — сразу завершим все проверки. Конечно, только в случае, если это не технический сотрудник, с ними разберёмся в первую очередь.
if user.tech_worker:
start()
elif user.age < 7 or user.weight > 110 or not user.ticket:
print('Поездка не состоялась')
else:
if user.age <= 14:
call_instructor()
validate_ticket(user)
start()
Кода стало сильно меньше! Теперь мы знаем, что если программа попала в ветку else, то значит, уже выполняется масса условий. Чтобы не дублировать код для проверки билета и старта поездки, мы создали вложенную ветку if. Она проверяет, что посетителю 14 лет или меньше, и в этом случае призывает инструктора.
На время прощаюсь. Мы рассмотрели базовые аспекты условных операторов на примере гипотетической системы, с которой вряд ли будут работать аналитики, однако их можно применять и для работы с таблицами в pandas. Пожалуйста, оставляйте свои вопросы, комментарии и отзывы — интересно узнать, хотите ли вы увидеть примеры использования условных операторов для анализа и обработки данных в pandas.
Busla
Прокомментирую немножко в сторону от основной темы статьи. Но почему такое странное именование переменных и функций:
В переменной night ждёшь увидеть скорее определение, что такое ночь — диапазон времени, например. Чуть дальше вводится функция is_tech_worker — проверка на ночь реализованная аналогичным образом была бы более читаема.
Почему проверка билета выглядит как
validate_ticket(user)
если естьuser.ticket
validate_ticket должен бы проверять/принимать билет, а не пользователя
Меня большинство курсов отвращает именно подобной неконсистентностью подачи: разбираешь пример, а в следующей главе оказывается что как в примере делать не стоит. Как бы автор ни акцентировал внимание на конкретном аспекте, примеры в голове откладываются целиком. Да и нередко учащиеся обращаются к учебникам давно пройденным главам как к справочнику, образцу хорошего тона для подражания и повторения.
Cairn Автор
Согласен, что для флага сейчас ночь или нет понятнее было бы
is_night_now
в качестве переменной для хранения флага. Хотелось, чтобы статья была доступна не только людям с большой насмотренностью, но и тем, у кого нет опыта в программировании, поэтому стремился к тому, чтобы названия с аргументами при переводе имели смысл. В данном случае — "проверить билет пользователя".