Мэтиз. Изучаем Python. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
Скачать 6.2 Mb.
|
aliens.py alien_0 = {'color': 'green', 'points': 5} alien_1 = {'color': 'yellow', 'points': 10} alien_2 = {'color': 'red', 'points': 15} Вложение 121 ❶ aliens = [alien_0, alien_1, alien_2] for alien in aliens: print(alien) Сначала создаются три словаря, каждый из которых представляет отдельного при- шельца. В точке каждый словарь заносится в список с именем aliens . Наконец, программа перебирает список и выводит каждого пришельца: {'color': 'green', 'points': 5} {'color': 'yellow', 'points': 10} {'color': 'red', 'points': 15} Конечно, в реалистичном примере будут использоваться более трех пришельцев, которые будут генерироваться автоматически. В следующем примере функция range() создает флот из 30 пришельцев: # Создание пустого списка для хранения пришельцев. aliens = [] # Создание 30 зеленых пришельцев. ❶ for alien_number in range(30): ❷ new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} ❸ aliens.append(new_alien) # Вывод первых 5 пришельцев: ❹ for alien in aliens[:5]: print(alien) print("...") # Вывод количества созданных пришельцев. ❺ print(f"Total number of aliens: {len(aliens)}") В начале примера список для хранения всех пришельцев, которые будут созданы, пуст. В точке функция range() возвращает множество чисел, которое просто сообщает Python, сколько раз должен повторяться цикл. При каждом выполнении цикла создается новый пришелец , который затем добавляется в список aliens . В точке сегмент используется для вывода первых пяти пришельцев, а в точке выводится длина списка (для демонстрации того, что программа действительно сгенерировала весь флот из 30 пришельцев): {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} Total number of aliens: 30 122 Глава 6 • Словари Все пришельцы обладают одинаковыми характеристиками, но Python рассматри- вает каждого пришельца как отдельный объект, что позволяет изменять атрибуты каждого владельца по отдельности. Как работать с таким множеством? Представьте, что в этой игре некоторые при- шельцы изменяют цвет и начинают двигаться быстрее. Когда приходит время сме- ны цветов, мы можем воспользоваться циклом for и командой if для изменения цвета. Например, чтобы превратить первых трех пришельцев в желтых, двигающих- ся со средней скоростью и приносящих игроку по 10 очков, можно действовать так: # Создание пустого списка для хранения пришельцев. aliens = [] # Создание 30 зеленых пришельцев. for alien_number in range (0,30): new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} aliens.append(new_alien) for alien in aliens[0:3]: if alien['color'] == 'green': alien['color'] = 'yellow' alien['speed'] = 'medium' alien['points'] = 10 # Вывод первых 5 пришельцев: for alien in aliens[0:5]: print(alien) print("...") Чтобы изменить первых трех пришельцев, мы перебираем элементы сегмента, включающего только первых трех пришельцев. В данный момент все пришельцы зеленые ( 'green' ), но так будет не всегда, поэтому мы пишем команду if , которая гарантирует, что изменяться будут только зеленые пришельцы. Если пришелец зеленый, то его цвет меняется на желтый ( 'yellow' ), скорость — на среднюю ( 'medium' ), а награда увеличивается до 10 очков: {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'medium', 'color': 'yellow', 'points': 10} {'speed': 'slow', 'color': 'green', 'points': 5} {'speed': 'slow', 'color': 'green', 'points': 5} Цикл можно расширить, добавив блок elif для превращения желтых пришельцев в красных — быстрых и приносящих игроку по 15 очков. Мы не станем приводить весь код, а цикл выглядит так: for alien in aliens[0:3]: if alien['color'] == 'green': alien['color'] = 'yellow' alien['speed'] = 'medium' alien['points'] = 10 Вложение 123 elif alien['color'] == 'yellow': alien['color'] = 'red' alien['speed'] = 'fast' alien['points'] = 15 Решение с хранением словарей в списке достаточно часто встречается тогда, когда каждый словарь содержит разные атрибуты одного объекта. Например, вы можете создать словарь для каждого пользователя сайта, как это было сделано в програм- ме user .py на с. 114, и сохранить отдельные словари в списке с именем users . Все словари в списке должны иметь одинаковую структуру, чтобы вы могли перебрать список и выполнить с каждым объектом словаря одни и те же операции. Список в словаре Вместо того чтобы помещать словарь в список, иногда бывает удобно поместить список в словарь. Представьте, как бы вы описали в программе заказанную пиццу. Если ограничиться только списком, сохранить удастся разве что список топпингов к пицце. При использовании словаря список топпингов может быть всего лишь одним аспектом описания пиццы. В следующем примере для каждой пиццы сохраняются два вида информации: осно- ва и список топпингов. Список топпингов представляет собой значение, связанное с ключом 'toppings' . Чтобы использовать элементы в списке, нужно указать имя словаря и ключ 'toppings' , как и для любого другого значения в словаре. Вместо одного значения будет получен список топпингов: pizza.py # Сохранение информации о заказанной пицце. ❶ pizza = { 'crust': 'thick', 'toppings': ['mushrooms', 'extra cheese'], } # Описание заказа. ❷ print(f"You ordered a {pizza['crust']}-crust pizza " "with the following toppings:") ❸ for topping in pizza['toppings']: print("\t" + topping) Работа начинается в точке со словаря с информацией о заказанной пицце. С ключом в словаре 'crust' связано строковое значение 'thick' . С другим ключом 'toppings' связано значение-список, в котором хранятся все заказанные топпинги. В точке выводится описание заказа перед созданием пиццы. Если вам нужно разбить длинную строку в вызове print() , выберите точку для разбиения выводи- мой строки и закончите строку кавычкой. Снабдите следующую строку отступом, добавьте открывающую кавычку и продолжите строку. Python автоматически объединяет все строки, обнаруженные в круглых скобках. Для вывода дополне- 124 Глава 6 • Словари ний пишется цикл for . Чтобы вывести список топпингов, мы используем ключ 'toppings' , а Python берет список топпингов из словаря. Следующее сообщение описывает пиццу, которую мы собираемся создать: You ordered a thick-crust pizza with the following toppings: mushrooms extra cheese Вложение списка в словарь может применяться каждый раз, когда с одним ключом словаря должно быть связано более одного значения. Если бы в предыдущем при- мере с языками программирования ответы сохранялись в списке, один участник опроса мог бы выбрать сразу несколько любимых языков. При переборе словаря значение, связанное с каждым человеком, представляло бы собой список языков (вместо одного языка). В цикле for словаря создается другой цикл для перебора списка языков, связанных с каждым участником: favorite_languages.py ❶ favorite_languages = { 'jen': ['python', 'ruby'], 'sarah': ['c'], 'edward': ['ruby', 'go'], 'phil': ['python', 'haskell'], } ❷ for name, languages in favorite_languages.items(): print(f"\n{name.title()}'s favorite languages are:") ❸ for language in languages: print(f"\t{language.title()}") Вы видите в точке , что значение, связанное с каждым именем, теперь представля- ет собой список. У некоторых участников один любимый язык программирования, у других таких языков несколько. При переборе словаря в точке переменная с именем languages используется для хранения каждого значения из словаря, пото- му что мы знаем, что каждое значение будет представлять собой список. В основном цикле по элементам словаря другой цикл перебирает элементы списка любимых языков каждого участника. Теперь каждый участник опроса может указать сколько угодно любимых языков программирования: Jen's favorite languages are: Python Ruby Sarah's favorite languages are: C Phil's favorite languages are: Python Haskell Вложение 125 Edward's favorite languages are: Ruby Go Чтобы дополнительно усовершенствовать программу, включите в начало цикла for словаря команду if для проверки того, выбрал ли данный участник более одного языка программирования (проверка основана на значении len(languages) ). Если у участника только один любимый язык, текст сообщения изменяется для един- ственного числа (например, «Sarah’s favorite language is C»). ПРИМЕЧАНИЕ Глубина вложения списков и словарей не должна быть слишком боль- шой . Если вам приходится вкладывать элементы на глубину существенно большую, чем в предыдущих примерах, или если вы работаете с чужим кодом со значительной глуби- ной вложения, скорее всего, у задачи существует более простое решение . Словарь в словаре Словарь также можно вложить в другой словарь, но в таких случаях код быстро усложняется. Например, если на сайте есть несколько пользователей с уникаль- ными именами, вы можете использовать имена пользователей как ключи в сло- варе. Информация о каждом пользователе при этом хранится в словаре, который используется как значение, связанное с именем. В следующем примере о каждом пользователе хранится три вида информации: имя, фамилия и место жительства. Чтобы получить доступ к этой информации, переберите имена пользователей и словарь с информацией, связанной с каждым именем: many_users.py users = { 'aeinstein': { 'first': 'albert', 'last': 'einstein', 'location': 'princeton', }, 'mcurie': { 'first': 'marie', 'last': 'curie', 'location': 'paris', }, } ❶ for username, user_info in users.items(): ❷ print(f"\nUsername: {username}") ❸ full_name = f"{user_info['first']} {user_info['last']}" location = user_info['location'] ❹ print(f"\tFull name: {full_name.title()}") print(f"\tLocation: {location.title()}") 126 Глава 6 • Словари В программе определяется словарь с именем users , содержащий два ключа: для пользователей 'aeinstein' и 'mcurie' . Значение, связанное с каждым ключом, представляет собой словарь с именем, фамилией и местом жительства пользова- теля. В процессе перебора словаря users в точке Python сохраняет каждый ключ в переменной username , а словарь, связанный с каждым именем пользователя, со- храняется в переменной user_info . Внутри основного цикла в словаре выводится имя пользователя . В точке начинается работа с внутренним словарем. Переменная user_info , со- держащая словарь с информацией о пользователе, содержит три ключа: 'first' , 'last' и 'location' . Каждый ключ используется для построения аккуратно от- форматированных данных с полным именем и местом жительства пользователя, с последующим выводом сводки известной информации о пользователе : Username: aeinstein Full name: Albert Einstein Location: Princeton Username: mcurie Full name: Marie Curie Location: Paris Обратите внимание на идентичность структур словарей всех пользователей. Хотя Python этого и не требует, наличие единой структуры упрощает работу с вложен- ными словарями. Если словари разных пользователей будут содержать разные ключи, то код в цикле for заметно усложнится. УПРАЖНЕНИЯ 6.7. Люди: начните с программы, написанной для упражнения 6.1 (с. 113). Создайте два но- вых словаря, представляющих разных людей, и сохраните все три словаря в списке с име- нем people . Переберите элементы списка людей. В процессе перебора выведите всю имею- щуюся информацию о каждом человеке. 6.8. Домашние животные: создайте несколько словарей, имена которых представляют клички домашних животных. В каждом словаре сохраните информацию о виде животно- го и имени владельца. Сохраните словари в списке с именем pets . Переберите элементы списка. В процессе перебора выведите всю имеющуюся информацию о каждом животном. 6.9. Любимые места: создайте словарь с именем favorite_places . Придумайте названия трех мест, которые станут ключами словаря, и сохраните для каждого человека от одного до трех любимых мест. Чтобы задача стала более интересной, опросите нескольких друзей и соберите реальные данные для своей программы. Переберите данные в словаре, выведите имя каждого человека и его любимые места. 6.10. Любимые числа: измените программу из упражнения 6.2 (с. 114), чтобы для каждого человека можно было хранить более одного любимого числа. Выведите имя каждого чело- века в списке и его любимые числа. 6.11. Города: создайте словарь с именем cities . Используйте названия трех городов в ка- честве ключей словаря. Создайте словарь с информацией о каждом городе; включите в него страну, в которой расположен город, примерную численность населения и один примеча- Итоги 127 тельный факт, относящийся к этому городу. Ключи словаря каждого города должны назы- ваться country , population и fact . Выведите название каждого города и всю сохраненную информацию о нем. 6.12. Расширение: примеры, с которыми мы работаем, стали достаточно сложными, и в них можно вносить разного рода усовершенствования. Воспользуйтесь одним из при- меров этой главы и расширьте его: добавьте новые ключи и значения, измените контекст программы или улучшите форматирование вывода. Итоги В этой главе вы научились определять словари и работать с хранящейся в них информацией. Вы узнали, как обращаться к отдельным элементам словаря и из- менять их, как перебрать всю информацию в словаре. Вы научились перебирать пары «ключ-значение», ключи и значения словаря. Также были рассмотрены воз- можности вложения словарей в список, вложения списков в словари и вложения словарей в другие словари. В следующей главе будут рассмотрены циклы while и получение входных данных от пользователей программ. Эта глава будет особенно интересной, потому что вы наконец-то сможете сделать свои программы интерактивными: они начнут реаги- ровать на действия пользователя. 7 Ввод данных и циклы while Программы обычно пишутся для решения задач конечного пользователя. Для этого им нужна некоторая информация, которую должен ввести пользователь. Про- стой пример: допустим, пользователь хочет узнать, достаточен ли его возраст для голосования. Если вы пишете программу для ответа на этот вопрос, то вам нужно будет узнать возраст пользователя. Программа должна запросить у пользователя значение — его возраст; когда у программы появятся данные, она может сравнить их с возрастом, дающим право на голосование, и сообщить результат. В этой главе вы узнаете, как получить пользовательский ввод (то есть входные данные), чтобы программа могла работать с ним. Если программа хочет получить отдельное имя, она запрашивает отдельное имя; если ей нужен список имен — она также выводит соответствующее сообщение. Для получения данных в программах используется функция input() Вы также научитесь продолжать работу программы, пока пользователь вводит новые данные; после получения всех данных программа переходит к работе с полу- ченной информацией. Цикл while в языке Python позволяет выполнять программу, пока некоторое условие остается истинным. Когда вы научитесь работать с пользовательским вводом и управлять продолжи- тельностью выполнения программы, вы сможете создавать полностью интерак- тивные программы. Как работает функция input() Функция input() приостанавливает выполнение программы и ожидает, пока пользователь введет некоторый текст. Получив ввод, Python сохраняет его в пере- менной, чтобы вам было удобнее работать с ним. Например, следующая программа предлагает пользователю ввести текст, а затем выводит сообщение для пользователя: parrot.py message = input("Tell me something, and I will repeat it back to you: ") print(message) Как работает функция input() 129 Функция input() получает один аргумент: текст подсказки (или инструкции), который выводится на экран, чтобы пользователь понимал, что от него требуется. В данном примере при выполнении первой строки пользователь видит подсказку с предложением ввести любой текст. Программа ожидает, пока пользователь введет ответ, и продолжает работу после нажатия Enter. Ответ сохраняется в переменной message , после чего вызов print(message) дублирует введенные данные: Tell me something, and I will repeat it back to you: Hello everyone! Hello everyone! ПРИМЕЧАНИЕ Sublime Text и многие другие текстовые редакторы не запускают про- граммы, запрашивающие входные данные у пользователя . Вы можете использовать эти редакторы для создания таких программ, но запускать их придется из терминального окна . См . «Запуск программ Python в терминале», с . 31 . Содержательные подсказки Каждый раз, когда в вашей программе используется функция input() , вы должны включать четкую, понятную подсказку, которая точно сообщит пользователю, какую информацию вы от него хотите получить. Подойдет любое предложение, которое объяснит пользователю, что нужно вводить. Пример: greeter.py name = input("Please enter your name: ") print(f"\nHello, {name}!") Добавьте пробел в конце подсказки (после двоеточия в предыдущем примере), чтобы отделить подсказку от данных, вводимых пользователем, и четко показать, где должен вводиться текст. Пример: Please enter your name: Eric Hello, Eric! Иногда подсказка занимает более одной строки. Например, вы можете сообщить пользователю, для чего программа запрашивает данные. Текст подсказки можно сохранить в переменной и передать эту переменную функции input() : вы строите длинное приглашение из нескольких строк, а потом выполняете одну компактную команду input() |