Программисту часто приходится проверять наборы условий и принимать решения в зависимости от этих условий. Команда if в языке Python позволяет проверить текущее состояние программы и выбрать дальнейшие действия в зависимости от результатов проверки.
В этой главе вы научитесь писать условные проверки для любых интересующих вас условий. Мы начнем с простых команд if, а затем перейдем к более сложным сериям команд if для проверки комбинированных условий. Затем эта концепция будет применена к спискам; вы узнаете, как написать цикл, который выполняет с большинством элементов списка одну операцию, и о том, что для некоторых элементов с конкретными значениями применяется особая обработка.
Следующий короткий пример показывает, как правильно организовать обработку специальных ситуаций с использованием if. Допустим, у вас имеется список машин, и вы хотите вывести название каждой машины. Названия большинства машин должны записываться с капитализацией (первая буква в верхнем регистре, остальные в нижнем). С другой стороны, значение 'bmw' должно записываться в верхнем регистре. Следующий код перебирает список названий машин и ищет в нем значение 'bmw'. Для всех элементов, содержащих значение 'bmw', значение выводится в верхнем регистре:
cars.py
cars = ['audi', 'bmw', 'subaru', 'toyota']
for car in cars:
(1) . .if car == 'bmw':
. . . .print(car.upper())
. .else:
. . . .print(car.title())
Цикл в этом примере (1) сначала проверяет, содержит ли car значение 'bmw'. Если проверка дает положительный результат, то значение выводится в верхнем регистре. Если car содержит все что угодно, кроме 'bmw', то при выводе значения применяется капитализация:
Audi
BMW
Subaru
Toyota
В этом примере объединяются несколько концепций, о которых вы узнаете в этой главе. Для начала рассмотрим основные конструкции, применяемые для проверки условий в программах.
В каждой команде if центральное место занимает выражение, результатом которого является логическая истина (True) или логическая ложь (False); это выражение называется условием. В зависимости от результата проверки Python решает, должен ли выполняться код в команде if. Если результат условия равен True, то Python выполняет код, следующий за командой if.
Во многих условиях текущее значение переменной сравнивается с конкретным значением, интересующим вас. Простейшее условие проверяет, равно ли значение переменной конкретной величине:
(1) >>> car = 'bmw'
(2)>>> car == 'bmw'
True
В строке (1) переменной car присваивается значение 'bmw'; операция выполняется одним знаком =, как вы уже неоднократно видели. Строка (2) проверяет, равно ли значение car строке 'bmw'; для проверки используется двойной знак равенства (==). Этот оператор возвращает True, если значения слева и справа от оператора равны; если же значения не совпадают, оператор возвращает False. В нашем примере значения совпадают, поэтому Python возвращает True.
Если car принимает любое другое значение вместо 'bmw', проверка возвращает False:
(1) >>> car = 'audi'
(2)>>> car == 'bmw'
False
Одиночный знак равенства выполняет операцию; код (1) можно прочитать в форме «Присвоить car значение 'audi'». С другой стороны, двойной знак равенства, как в строке (2), задает вопрос: «Значение car равно 'bmw'?» Такое применение знаков равенства встречается во многих языках программирования.
В языке Python проверка равенства выполняется с учетом регистра. Например, два значения с разным регистром символов равными не считаются:
>>> car = 'Audi'
>>> car == 'audi'
False
Если регистр символов важен, такое поведение приносит пользу. Но если проверка должна выполняться на уровне символов без учета регистра, преобразуйте значение переменной к нижнему регистру перед выполнением сравнения:
>>> car = 'Audi'
>>> car.lower() == 'audi'
True
Условие возвращает True независимо от регистра символов 'Audi', потому что проверка теперь выполняется без учета регистра. Функция lower() не изменяет значения, которое изначально хранилось в car, так что сравнение не отражается на исходной переменной:
(1) >>> car = 'Audi'
(2)>>> car.lower() == 'audi'
True
(3)>>> car
'Audi'
В точке (1) строка 'Audi' сохраняется в переменной car. В точке (2) значение car приводится к нижнему регистру и сравнивается со значением строки 'audi', также записанным в нижнем регистре. Две строки совпадают, поэтому Python возвращает True. Вывод в точке (3) показывает, что значение, хранящееся в car, не изменилось в результате проверки.
Веб-сайты устанавливают определенные правила для данных, вводимых пользователями подобным образом. Например, сайт может использовать проверку условия, чтобы убедиться в том, что имя каждого пользователя уникально (а не совпадает с именем другого пользователя, отличаясь от него только регистром символов). Когда кто-то указывает новое имя пользователя, это имя преобразуется к нижнему регистру и сравнивается с версиями всех существующих имен в нижнем регистре. Во время такой проверки имя 'John' будет отклонено, если в системе уже используется любая разновидность 'john'.
Если вы хотите проверить, что два значения различны, используйте комбинацию из восклицательного знака и знака равенства (!=). Восклицательный знак представляет отрицание, как и во многих языках программирования.
Для знакомства с оператором неравенства мы воспользуемся другой командой if. В переменной хранится заказанное дополнение к пицце; если клиент не заказал анчоусы (anchovies), программа выводит сообщение:
toppings.py
requested_topping = 'mushrooms'
(1) if requested_topping != 'anchovies':
. .print("Hold the anchovies!")
Строка (1) сравнивает значение requested_topping со значением 'anchovies'. Если эти два значения не равны, Python возвращает True и выполняет код после команды if. Если два значения равны, Python возвращает False и не выполняет код после команды if. Так как значение requested_topping отлично от 'anchovies', команда print будет выполнена:
Hold the anchovies!
В большинстве условных выражений, которые вы будете использовать в программах, будет проверяться равенство, но иногда проверка неравенства оказывается более эффективной.
Проверка числовых значений достаточно прямолинейна. Например, следующий код проверяет, что переменная age равна 18:
>>> age = 18
>>> age == 18
True
Также можно проверить условие неравенства двух чисел. Например, следующий код выводит сообщение, если значение переменной answer отлично от ожидаемого:
magic_ number.py
answer = 17
(1) if answer != 42:
. .print("That is not the correct answer. Please try again!")
Условие (1) выполняется, потому что значение answer (17) не равно 42. Так как условие истинно, блок с отступом выполняется:
That is not the correct answer. Please try again!
В условные команды также можно включать всевозможные математические сравнения: меньше, меньше или равно, больше, больше или равно:
>>> age = 19
>>> age < 21
True
>>> age <= 21
True
>>> age > 21
False
>>> age >= 21
False
Все эти математические сравнения могут использоваться в условиях if, что повышает точность формулировки интересующих вас условий.
Иногда требуется проверить несколько условий одновременно. Например, в некоторых случаях для выполнения действия бывает нужно, чтобы истинными были сразу два условия; в других случаях достаточно, чтобы истинным было хотя бы одно из двух условий. Ключевые слова and и or помогут вам в подобных ситуациях.
Чтобы проверить, что два условия истинны одновременно, объедините их ключевым словом and; если оба условия истинны, то и все выражение тоже истинно. Если хотя бы одно (или оба) условия ложны, то и результат всего выражения равен False.
Например, чтобы убедиться в том, что каждому из двух людей больше 21 года, используйте следующую проверку:
(1) >>> age_0 = 22
>>> age_1 = 18
(2)>>> age_0 >= 21 and age_1 >= 21
False
(3) >>> age_1 = 22
>>> age_0 >= 21 and age_1 >= 21
True
В точке (1) определяются две переменные, age_0 и age_1. В точке (2) программа проверяет, что оба значения равны 21 и более. Левое условие выполняется, а правое нет, поэтому все условное выражение дает результат False. В точке (3) переменной age_1 присваивается значение 22. Теперь значение age_1 больше 21; обе проверки проходят, а все условное выражение дает истинный результат.
Чтобы код лучше читался, отдельные условия можно заключить в круглые скобки, но это не обязательно. С круглыми скобками проверка может выглядеть так:
(age_0 >= 21) and (age_1 >= 21)
Ключевое слово or тоже позволяет проверить несколько условий, но результат общей проверки является истинным в том случае, когда истинно хотя бы одно или оба условия. Ложный результат достигается только в том случае, если оба отдельных условия ложны.
Вернемся к примеру с возрастом, но на этот раз проверим, что хотя бы одна из двух переменных больше 21:
(1) >>> age_0 = 22
>>> age_1 = 18
(2)>>> age_0 >= 21 or age_1 >= 21
True
(3)>>> age_0 = 18
>>> age_0 >= 21 or age_1 >= 21
False
Как и в предыдущем случае, в точке (1) определяются две переменные. Так как условие для age_0 в точке (2) истинно, все выражение также дает истинный результат. Затем значение age_0 уменьшается до 18. При проверке (3) оба условия оказываются ложными, и общий результат всего выражения тоже ложен.
Иногда бывает важно проверить, содержит ли список некоторое значение, прежде чем выполнять действие. Например, перед завершением регистрации нового пользователя на сайте можно проверить, существует ли его имя в списке имен действующих пользователей, или в картографическом проекте определить, входит ли передаваемое место в список известных мест на карте.
Чтобы узнать, присутствует ли заданное значение в списке, воспользуйтесь ключевым словом in. Допустим, вы пишете программу для пиццерии. Вы создали список дополнений к пицце, заказанных клиентом, и хотите проверить, входят ли некоторые дополнения в этот список.
>>> requested_toppings = ['mushrooms', 'onions', 'pineapple']
(1) >>> 'mushrooms' in requested_toppings
True
(2)>>> 'pepperoni' in requested_toppings
False
В точках (1) и (2) ключевое слово in приказывает Python проверить, входят ли значения 'mushrooms' и 'pepperoni' в список requested_toppings. Это весьма полезно, потому что вы можете создать список значений, критичных для вашей программы, а затем легко проверить, присутствует ли проверяемое значение в списке.
В других случаях программа должна убедиться в том, что значение не входит в список. Для этого используется ключевое слово not. Для примера рассмотрим список пользователей, которым запрещено писать комментарии на форуме. Прежде чем разрешить пользователю отправку комментария, можно проверить, не был ли пользователь включен в «черный список»:
banned_users.py
banned_users = ['andrew', 'carolina', 'david']
user = 'marie'
(1) if user not in banned_users:
. .print(user.title() + ", you can post a response if you wish.")
Строка (1) достаточно четко читается: если пользователь не входит в «черный список» banned_users, то Python возвращает True и выполняет строку с отступом. Пользователь 'marie' в этот список не входит, поэтому программа выводит соответствующее сообщение:
Marie, you can post a response if you wish.
В процессе изучения программирования вы рано или поздно услышите термин «логическое выражение». По сути это всего лишь другое название для проверки условия. Результат логического выражения равен True или False, как и результат условного выражения после его вычисления.
Логические выражения часто используются для проверки некоторых условий — например, запущена ли компьютерная игра или разрешено ли пользователю редактирование некоторой информации на сайте:
game_active = True
can_edit = False
Логические выражения предоставляют эффективные средства для контроля состояния программы или определенного условия, играющего важную роль в вашей программе.
Упражнения
5-1. Проверка условий: напишите последовательность условий. Выведите описание каждой проверки и ваш прогноз относительно ее результата. Код должен выглядеть примерно так:
car = 'subaru'
print("Is car == 'subaru'? I predict True.")
print(car == 'subaru')
print("\nIs car == 'audi'? I predict False.")
print(car == 'audi')
• Внимательно просмотрите результаты. Убедитесь в том, что вы понимаете, почему результат каждой строки равен True или False.
• Создайте как минимум 10 условий. Не менее 5 должны давать результат True, а не менее 5 других — результат False.
5-2. Больше условий: количество условий не ограничивается 10. Попробуйте написать другие условия и включить их в conditional_tests.py. Программа должна выдавать по крайней мере один истинный и один ложный результат для следующих видов проверок.
• Проверка равенства и неравенства строк.
• Проверки с использованием функции lower().
• Числовые проверки равенства и неравенства, условий «больше», «меньше», «больше или равно», «меньше или равно».
• Проверки с ключевым словом and и or.
• Проверка вхождения элемента в список.
• Проверка отсутствия элемента в списке.
Когда вы поймете, как работают проверки условий, можно переходить к написанию команд if. Существуют несколько разновидностей команд if, и выбор варианта зависит от количества проверяемых условий. Примеры команд if уже встречались вам при обсуждении проверки условий, но сейчас эта тема будет рассмотрена более подробно.
Простейшая форма команды if состоит из одного условия и одного действия:
if условие:
. .действие
В первой строке размещается условие, а в блоке с отступом — практически любое действие. Если условие истинно, то Python выполняет код в блоке после команды if, а если ложно, этот код игнорируется.
Допустим, имеется переменная, представляющая возраст человека. Следующий код проверяет, что этот возраст достаточен для голосования:
voting.py
age = 19
(1) if age >= 18:
(2) . .print("You are old enough to vote!")
В точке (1) Python проверяет, что значение переменной age больше или равно 18. В таком случае выполняется команда print (2) в строке с отступом:
You are old enough to vote!
Отступы в командах if играют ту же роль, что и в циклах for. Если условие истинно, то все строки с отступом после команды if выполняются, а если ложно — весь блок с отступом игнорируется.
Блок команды if может содержать сколько угодно строк. Добавим еще одну строку для вывода дополнительного сообщения в том случае, если возраст достаточен для голосования:
age = 19
if age >= 18:
print("You are old enough to vote!")
. .print("Have you registered to vote yet?")
Условие выполняется, а обе команды print снабжены отступом, поэтому выводятся оба сообщения:
You are old enough to vote!
Have you registered to vote yet?
Если значение age меньше 18, программа ничего не выводит.
Часто в программе необходимо выполнить одно действие в том случае, если условие истинно, и другое действие, если оно ложно. С синтаксисом if-else это возможно. Блок if-else в целом похож на команду if, но секция else определяет действие или набор действий, выполняемых при неудачной проверке.
В следующем примере выводится то же сообщение, которое выводилось ранее, если возраст достаточен для голосования, но на этот раз при любом другом возрасте выводится другое сообщение:
age = 17
(1) if age >= 18:
print("You are old enough to vote!")
print("Have you registered to vote yet?")
(2)else:
. .print("Sorry, you are too young to vote.")
. .print("Please register to vote as soon as you turn 18!")
Если условие (1) истинно, то выполняется первый блок с командами print. Если же условие ложно, выполняется блок else в точке (2). Так как значение age на этот раз меньше 18, условие оказывается ложным, и выполняется код в блоке else:
Sorry, you are too young to vote.
Please register to vote as soon as you turn 18!
Этот код работает, потому что существуют всего две возможные ситуации: возраст либо достаточен для голосования, либо недостаточен. Структура if-else хорошо подходит для тех ситуаций, в которых Python всегда выполняет только одно из двух возможных действий. В подобных простых цепочках if-else всегда выполняется одно из двух возможных действий.
Нередко в программе требуется проверять более двух возможных ситуаций; для таких ситуаций в Python предусмотрен синтаксис if-elif-else. Python выполняет только один блок в цепочке if-elif-else. Все условия проверяются по порядку до тех пор, пока одно из них не даст истинный результат. Далее выполняется код, следующий за этим условием, а все остальные проверки Python пропускает.
Во многих реальных ситуациях существуют более двух возможных результатов. Представьте себе парк аттракционов, который взимает разную плату за вход для разных возрастных групп:
• Для посетителей младше 4 лет вход бесплатный.
• Для посетителей от 4 до 18 лет билет стоит $5.
• Для посетителей от 18 лет и старше билет стоит $10.
Как использовать команду if для определения платы за вход? Следующий код определяет, к какой возрастной категории относится посетитель, и выводит сообщение со стоимостью билета:
amusement_park.py
age = 12
(1) if age < 4:
. .print("Your admission cost is $0.")
(2)elif age < 18:
. .print("Your admission cost is $5.")
(3)else:
. .print("Your admission cost is $10.")
Условие if в точке (1) проверяет, что возраст посетителя меньше 4 лет. Если условие истинно, то программа выводит соответствующее сообщение, и Python пропускает остальные проверки. Строка elif в точке (2) в действительности является еще одной проверкой if, которая выполняется только в том случае, если предыдущая проверка завершилась неудачей. В этом месте цепочки известно, что возраст посетителя не меньше 4 лет, потому что первое условие было ложным. Если посетителю меньше 18 лет, программа выводит соответствующее сообщение, и Python пропускает блок else. Если ложны оба условия — if и elif, то Python выполняет код в блоке else в точке (3).
В данном примере условие (1) дает ложный результат, поэтому его блок не выполняется. Однако второе условие оказывается истинным (12 меньше 18), поэтому код будет выполнен. Вывод состоит из одного сообщения с ценой билета:
Your admission cost is $5.
При любом значении возраста больше 17 первые два условия ложны. В таких ситуациях блок else будет выполнен, и цена билета составит $10.
Вместо того чтобы выводить сообщение с ценой билета в блоках if-elif-else, лучше использовать другое, более компактное решение: присвоить цену в цепочке if-elif-else, а затем добавить одну команду print после выполнения цепочки:
age = 12
if age < 4:
(1) . .price = 0
elif age < 18:
(2) . .price = 5
else:
(3) . .price = 10
(4)print("Your admission cost is $" + str(price) + ".")
Строки (1) , (2) и (3) присваивают значение price в зависимости от значения age, как и в предыдущем примере. После присваивания цены в цепочке if-elif-else отдельная команда print без отступа (4) использует это значение для вывода сообщения с ценой билета.
Этот пример выводит тот же результат, что и предыдущий, но цепочка if-elif-else имеет более четкую специализацию. Вместо того чтобы определять цену и выводить сообщения, она просто определяет цену билета. Кроме повышения эффективности, у этого кода есть дополнительное преимущество: лучшая изменяемость. Чтобы изменить текст выходного сообщения, достаточно будет отредактировать всего одну команду print — вместо трех разных команд.
Код может содержать сколько угодно блоков elif. Например, если парк аттракционов введет особую скидку для пожилых посетителей, вы можете добавить в свой код еще одну проверку для определения того, распространяется ли скидка на текущего посетителя. Допустим, посетители с возрастом 65 и выше платят половину от обычной цены билета, или $5:
age = 12
if age < 4:
price = 0
elif age < 18:
price = 5
(1) elif age < 65:
. .price = 10
(2)else:
. .price = 5
print("Your admission cost is $" + str(price) + ".")
Бульшая часть кода осталась неизменной. Второй блок elif в точке (1) теперь убеждается в том, что посетителю меньше 65 лет, прежде чем назначить ему полную цену билета $10. Обратите внимание: значение, присвоенное в блоке else (2), должно быть заменено на $5, потому что до этого блока доходят только посетители с возрастом 65 и выше.
Python не требует, чтобы цепочка if-elif непременно завершалась блоком else. Иногда блок else удобен; в других случаях бывает нагляднее использовать дополнительную секцию elif для обработки конкретного условия:
age = 12
if age < 4:
price = 0
elif age < 18:
price = 5
elif age < 65:
price = 10
(1) elif age >= 65:
price = 5
print("Your admission cost is $" + str(price) + ".")
Блок elif в точке (1) назначает цену $5, если возраст посетителя равен 65 и выше; смысл такого кода более понятен, чем у обобщенного блока else. С таким изменением выполнение каждого блока возможно только при истинности конкретного условия.
Блок else «универсален»: он обрабатывает все условия, не подходящие ни под одну конкретную проверку if или elif, причем в эту категорию иногда могут попасть недействительные или даже вредоносные данные. Если у вас имеется завершающее конкретное условие, лучше используйте завершающий блок elif и опустите блок else. В этом случае вы можете быть уверены в том, что ваш код будет выполняться только в правильных условиях.
Цепочки if-elif-else эффективны, но они подходят только в том случае, если истинным должно быть только одно условие. Как только Python находит выполняющееся условие, все остальные проверки пропускаются. Такое поведение достаточно эффективно, потому что оно позволяет проверить одно конкретное условие.
Однако иногда бывает важно проверить все условия, представляющие интерес. В таких случаях следует применять серии простых команд if без блоков elif или else. Такое решение уместно, когда истинными могут быть сразу несколько условий и вы хотите отреагировать на все истинные условия.
Вернемся к примеру с пиццей. Если кто-то закажет пиццу с двумя дополнениями, программа должна обработать оба дополнения:
toppings.py
(1) requested_toppings = ['mushrooms', 'extra cheese']
(2)if 'mushrooms' in requested_toppings:
. .print("Adding mushrooms.")
(3)if 'pepperoni' in requested_toppings:
. .print("Adding pepperoni.")
(4)if 'extra cheese' in requested_toppings:
. .print("Adding extra cheese.")
. .
print("\nFinished making your pizza!")
Обработка начинается в точке (1) со списка, содержащего заказанные дополнения. Команды if в точке (2) и (3) проверяют, включает ли заказ конкретные дополнения — грибы и пепперони, и если включает — выводят подтверждающее сообщение. Проверка в точке (3) реализована простой командой if, а не elif или else, поэтому условие будет проверяться независимо от того, было ли предыдущее условие истинным или ложным. Код в точке (4) проверяет, была ли заказана дополнительная порция сыра, независимо от результата первых двух проверок. Эти три независимых условия проверяются при каждом выполнении программы.
Так как в этом коде проверяются все возможные варианты дополнений, в заказ будут включены два дополнения из трех:
Adding mushrooms.
Adding extra cheese.
Finished making your pizza!
Если бы в программе использовался блок if-elif-else, код работал бы неправильно, потому что он прерывал работу после обнаружения первого истинного условия. Вот как это выглядело бы:
requested_toppings = ['mushrooms', 'extra cheese']
if 'mushrooms' in requested_toppings:
print("Adding mushrooms.")
elif 'pepperoni' in requested_toppings:
print("Adding pepperoni.")
elif 'extra cheese' in requested_toppings:
print("Adding extra cheese.")
print("\nFinished making your pizza!")
Первое же проверяемое условие (для 'mushrooms') оказывается истинным. Однако значения 'extra cheese' и 'pepperoni' после этого не проверяются, потому что в цепочках if-elif-else после обнаружения первого истинного условия все остальные условия пропускаются. В результате в пиццу будет включено только первое из заказанных дополнений:
Adding mushrooms.
Finished making your pizza!
Итак, если вы хотите, чтобы в программе выполнялся только один блок кода, — используйте цепочку if-elif-else. Если же выполняться должны несколько блоков, используйте серию независимых команд if.
Упражнения
5-3. Цвета 1: представьте, что в вашей компьютерной игре только что был подбит корабль пришельцев. Создайте переменную с именем alien_color и присвойте ей значение ‘green’, ‘yellow’ или ‘red’.
• Напишите команду if для проверки того, что переменная содержит значение ‘green’. Если условие истинно, выведите сообщение о том, что игрок только что заработал 5 очков.
• Напишите одну версию программы, в которой условие if выполняется, и другую версию, в которой оно не выполняется. (Во второй версии никакое сообщение выводиться не должно.)
5-4. Цвета 2: выберите цвет, как это было сделано в упражнении 5-3, и напишите цепочку if-else.
• Напишите команду if для проверки того, что переменная содержит значение ‘green’. Если условие истинно, выведите сообщение о том, что игрок только что заработал 5 очков.
• Если переменная содержит любое другое значение, выведите сообщение о том, что игрок только что заработал 10 очков.
• Напишите одну версию программы, в которой выполняется блок if, и другую версию, в которой выполняется блок else.
5-5. Цвета 3: преобразуйте цепочку if-else из упражнения 5-4 в цепочку if-elif-else.
• Если переменная содержит значение 'green’, выведите сообщение о том, что игрок только что заработал 5 очков.
• Если переменная содержит значение 'yellow’, выведите сообщение о том, что игрок только что заработал 10 очков.
• Если переменная содержит значение 'red’, выведите сообщение о том, что игрок только что заработал 15 очков.
• Напишите три версии программы и проследите за тем, чтобы для каждого цвета пришельца выводилось соответствующее сообщение.
5-6. Периоды жизни: напишите цепочку if-elif-else для определения периода жизни человека. Присвойте значение переменной age, а затем выведите сообщение.
• Если значение меньше 2 — младенец.
• Если значение больше или равно 2, но меньше 4 — малыш.
• Если значение больше или равно 4, но меньше 13 — ребенок.
• Если значение больше или равно 13, но меньше 20 — подросток.
• Если значение больше или равно 20, но меньше 65 — взрослый.
• Если значение больше или равно 65 — пожилой человек.
5-7. Любимый фрукт: составьте список своих любимых фруктов. Напишите серию независимых команд if для проверки того, присутствуют ли некоторые фрукты в списке.
• Создайте список трех своих любимых фруктов и назовите его favorite_fruits.
• Напишите пять команд if. Каждая команда должна проверять, входит ли определенный тип фрукта в список. Если фрукт входит в список, блок if должен выводить сообщение вида «You really like bananas!».
Объединение команд if со списками открывает ряд интересных возможностей. Например, вы можете отслеживать специальные значения, для которых необходима особая обработка по сравнению с другими значениями в списке, или эффективно управлять изменяющимися условиями — например, наличием некоторых блюд в ресторане. Также объединение команд if со списками помогает продемонстрировать, что ваш код корректно работает во всех возможных ситуациях.
Эта глава началась с простого примера, показывающего, как обрабатывать особые значения (такие, как 'bmw'), которые должны выводиться в другом формате по сравнению с другими значениями в списке. Теперь, когда вы лучше разбираетесь в проверках условий и командах if, давайте повнимательнее рассмотрим процесс поиска и обработки особых значений в списке.
Вернемся к примеру с пиццерией. Программа выводит сообщение каждый раз, когда пицца снабжается дополнением в процессе приготовления. Код этого действия можно записать чрезвычайно эффективно: нужно создать список дополнений, заказанных клиентом, и использовать цикл для перебора всех заказанных дополнений:
toppings.py
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
. .print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
Вывод достаточно тривиален, поэтому код сводится к простому циклу for:
Adding mushrooms.
Adding green peppers.
Adding extra cheese.
Finished making your pizza!
А если в пиццерии вдруг кончится зеленый перец? Команда if в цикле for может правильно обработать эту ситуацию:
requested_toppings = ['mushrooms', 'green peppers', 'extra cheese']
for requested_topping in requested_toppings:
(1) if requested_topping == 'green peppers':
. . . .print("Sorry, we are out of green peppers right now.")
(2) else:
print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
На этот раз программа проверяет каждый заказанный элемент перед добавлением его к пицце. В точке (1) программа проверяет, заказал ли клиент зеленый перец, и если заказал — выводит сообщение о том, что этого дополнения нет. Блок else в точке (2) гарантирует, что все другие дополнения будут включены в заказ.
Из выходных данных видно, что все заказанные дополнения обрабатываются правильно:
Adding mushrooms.
Sorry, we are out of green peppers right now.
Adding extra cheese.
Finished making your pizza!
Для всех списков, с которыми мы работали до сих пор, действовало одно простое предположение: мы считали, что в каждом списке есть хотя бы один элемент. Скоро мы предоставим пользователю возможность вводить информацию, хранящуюся в списке, поэтому мы уже не можем предполагать, что при каждом выполнении цикла в списке есть хотя бы один элемент. В такой ситуации перед выполнением цикла for будет полезно проверить, есть ли в списке хотя бы один элемент.
Проверим, есть ли элементы в списке заказанных дополнений, перед изготовлением пиццы. Если список пуст, программа предлагает пользователю подтвердить, что он хочет базовую пиццу без дополнений. Если список не пуст, пицца готовится так же, как в предыдущих примерах:
(1) requested_toppings = []
(2)if requested_toppings:
for requested_topping in requested_toppings:
print("Adding " + requested_topping + ".")
print("\nFinished making your pizza!")
(3)else:
. .print("Are you sure you want a plain pizza?")
На этот раз мы начинаем с пустого списка заказанных дополнений в точке (1) . Вместо того чтобы сразу переходить к циклу for, программа выполняет проверку в точке (2). Когда имя списка используется в условии if, Python возвращает True, если список содержит хотя бы один элемент; если список пуст, возвращается значение False. Если requested_toppings проходит проверку условия, выполняется тот же цикл for, который мы использовали в предыдущем примере. Если же условие ложно, то программа выводит сообщение, которое предлагает клиенту подтвердить, действительно ли он хочет получить базовую пиццу без дополнений (3).
В данном примере список пуст, поэтому выводится сообщение:
Are you sure you want a plain pizza?
Если в списке есть хотя бы один элемент, в выходные данные включается каждое заказанное дополнение.
Посетители способны заказать что угодно, особенно когда речь заходит о дополнениях к пицце. Что если клиент захочет положить на пиццу картофель фри? Списки и команды if позволят вам убедиться в том, что входные данные имеют смысл, прежде чем обрабатывать их.
Давайте проверим наличие нестандартных дополнений перед тем, как готовить пиццу. В следующем примере определяются два списка. Первый список содержит перечень доступных дополнений, а второй — список дополнений, заказанных клиентом. На этот раз каждый элемент из requested_toppings проверяется по списку доступных дополнений перед добавлением в пиццу:
(1) available_toppings = ['mushrooms', 'olives', 'green peppers',
. . . . . . . . . . 'pepperoni', 'pineapple', 'extra cheese']
(2)requested_toppings = ['mushrooms', 'french fries', 'extra cheese']
(3)for requested_topping in requested_toppings:
(4) . .if requested_topping in available_toppings:
. . . .print("Adding " + requested_topping + ".")
(5) . .else:
. . . .print("Sorry, we don't have " + requested_topping + ".")
. . . .
print("\nFinished making your pizza!")
В точке (1) определяется список доступных дополнений к пицце. Стоит заметить, что если в пиццерии используется постоянный ассортимент дополнений, этот список можно реализовать в виде кортежа. В точке (2) создается список дополнений, заказанных клиентом. Обратите внимание на необычный заказ 'french fries'. В точке (3) программа перебирает список заказанных дополнений. Внутри цикла программа сначала проверяет, что каждое заказанное дополнение присутствует в списке доступных дополнений (4). Если дополнение доступно, оно добавляется в пиццу. Если заказанное дополнение не входит в список, выполняется блок else (5). Блок else выводит сообщение о том, что дополнение недоступно.
С этим синтаксисом программа выдает четкий, содержательный вывод:
Adding mushrooms.
Sorry, we don't have french fries.
Adding extra cheese.
Finished making your pizza!
Всего в нескольких строках кода нам удалось эффективно решить вполне реальную проблему!
Упражнения
5-8. Hello Admin: создайте список из пяти и более имен пользователей, включающий имя ‘admin’. Представьте, что вы пишете код, который выводит приветственное сообщение для каждого пользователя после его входа на сайт. Переберите элементы списка и выведите сообщение для каждого пользователя.
• Для пользователя с именем 'admin’ выведите особое сообщение — например: «Hello admin, would you like to see a status report?»
• В остальных случаях выводите универсальное приветствие — например: «Hello Eric, thank you for logging in again».
5-9. Без пользователей: добавьте в hello_admin.py команду if, которая проверит, что список пользователей не пуст.
• Если список пуст, выведите сообщение: «We need to find some users!»
• Удалите из списка все имена пользователей и убедитесь в том, что программа выводит правильное сообщение.
5-10. Проверка имен пользователей: выполните следующие действия для создания программы, моделирующей проверку уникальности имен пользователей.
• Создайте список current_users, содержащий пять и более имен пользователей.
• Создайте другой список new_users, содержащий пять и более имен пользователей. Убедитесь в том, что одно или два новых имени также присутствуют в списке current_users.
• Переберите список new_users и для каждого имени в этом списке проверьте, было ли оно использовано ранее. Если имя уже использовалось, выведите сообщение о том, что пользователь должен выбрать новое имя. Если имя не использовалось, выведите сообщение о его доступности.
• Проследите за тем, чтобы сравнение выполнялось без учета регистра символов. Если имя 'John’ уже используется, в регистрации имени ‘JOHN’ следует отказать.
5-11. Порядковые числительные: порядковые числительные в английском языке заканчиваются суффиксом th (кроме 1st, 2nd и 3rd).
• Сохраните числа от 1 до 9 в списке.
• Переберите элементы списка.
• Используйте цепочку if-elif-else в цикле для вывода правильного окончания числительного для каждого числа. Программа должна выводить числительные «1st 2nd 3rd 4th 5th 6th 7th 8th 9th», причем каждый результат должен располагаться в отдельной строке.
Во всех примерах этой главы применялись правила стилевого оформления. В PEP 8 приведена только одна рекомендация, касающаяся проверки условий: заключать операторы сравнения (такие, как ==, >=, <= и т.д.) в одиночные пробелы. Например, запись
if age < 4:
лучше, чем:
if age<4:
Пробелы не влияют на интерпретацию вашего кода Python; они только упрощают чтение кода вами и другими разработчиками.
Упражнения
5-12. Стиль оформления команд if: проанализируйте программы, написанные в этой главе, и проверьте, правильно ли вы оформляли условия.
5-13. Ваши идеи: к этому моменту вы уже стали более квалифицированным программистом, чем в начале книги. Теперь вы лучше представляете, как в программах моделируются явления реального мира, и сможете сами придумать задачи, которые будут решаться в ваших программах. Запишите несколько задач, которые вам хотелось бы решить с ростом вашего профессионального мастерства. Может быть, это какие-то компьютерные игры, задачи анализа наборов данных или веб-приложения?
В этой главе вы научились писать условия, результатом которых всегда является логическое значение (True или False.) Вы научились писать простые команды if, цепочки if-else и цепочки if-elif-else. Вы начали использовать эти структуры для выявления конкретных условий, которые необходимо проверить, и проверки этих условий в ваших программах. Вы узнали, как обеспечить специальную обработку некоторых элементов в списке с сохранением эффективности циклов for. Также мы вернулись к стилевым рекомендациям Python, с которыми более сложные программы становятся относительно простыми для чтения и понимания.
В главе 6 рассматриваются словари Python. Словарь отчасти напоминает список, но он позволяет связывать разные виды информации. Вы научитесь создавать словари, перебирать их элементы, использовать их в сочетании со списками и командами if. Словари помогут вам моделировать еще более широкий спектр реальных ситуаций.