Книга Изучаем Python
Скачать 4.68 Mb.
|
ПРИМЕЧАНИЕ В большинстве редакторов предусмотрены функции, упрощающие форматирование расширенных списков и словарей в описанном стиле . Также существуют другие распространенные способы фор- матирования длинных словарей — вы можете столкнуться с ними в вашем редакторе или в другом источнике . Для заданного имени участника опроса этот словарь позволяет легко определить его любимый язык: favorite_languages.py favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } print("Sarah's favorite language is " + favorite_languages['sarah'].title() + ".") Перебор словаря 107 Чтобы узнать, какой язык выбран пользователем с именем Sarah , мы запрашиваем следующее значение: favorite_languages['sarah'] Этот синтаксис используется в команде вывода , а результат содержит значение, связанное с ключом: Sarah's favorite language is C. Этот пример также показывает, как разбить длинную команду print на несколько строк. Слово print короче большинства имен словарей, поэтому есть смысл вклю- чить первую часть выводимого текста сразу же за открывающей круглой скоб- кой . Выберите точку, в которой будет разбиваться вывод, и добавьте оператор конкатенации ( + ) в конец первой строки . Нажмите Enter, а затем клавишу Tab для выравнивания всех последующих строк на один уровень отступа под командой print . Завершив построение вывода, поставьте закрывающую круглую скобку в по- следней строке блока print . УПРАЖНЕНИЯ 6-1 . Человек: используйте словарь для сохранения информации об известном вам чело- веке . Сохраните имя, фамилию, возраст и город, в котором живет этот человек . Словарь должен содержать ключи с такими именами, как first_name, last_name, age и city . Выведите каждый фрагмент информации, хранящийся в словаре . 6-2 . Любимые числа: используйте словарь для хранения любимых чисел . Возьмите пять имен и используйте их как ключи словаря . Придумайте любимое число для каждого чело- века и сохраните его как значение в словаре . Выведите имя каждого человека и его люби- мое число . Чтобы задача стала более интересной, опросите нескольких друзей и соберите реальные данные для своей программы . 6-3 . Глоссарий: словари Python могут использоваться для моделирования «настоящего» словаря (чтобы не создавать путаницы, назовем его «глоссарием») . • Вспомните пять терминов из области программирования, которые вы узнали в пре- дыдущих главах . Используйте эти слова как ключи глоссария, а их определения — как значения . • Выведите каждое слово и его определение в аккуратно отформатированном виде . Например, вы можете вывести слово, затем двоеточие и определение; или же слово в одной строке, а его определение — с отступом в следующей строке . Используйте символ новой строки (\n) для вставки пустых строк между парами «слово-определе- ние» в выходных данных . Перебор словаря Словарь Python может содержать как несколько пар «ключ—значение», так и мил- лионы таких пар. Поскольку в словаре может храниться большой объем данных, Python предоставляет средства для перебора элементов словаря. Информация может храниться в словарях по-разному, поэтому предусмотрены разные способы перебора. Программа может перебрать все пары «ключ—значение» в словаре, толь- ко ключи или только значения. 108 Глава 6 • Словари Перебор всех пар «ключ—значение» Прежде чем ознакомиться с разными способами перебора, рассмотрим новый словарь, предназначенный для хранения информации о пользователе веб-сайта. В следующем словаре хранится имя пользователя, его имя и фамилия: user_0 = { 'username': 'efermi', 'first': 'enrico', 'last': 'fermi', } То, что вы уже узнали в этой главе, позволит вам обратиться к любому отдель ному атрибуту user_0 . Но что если вы хотите просмотреть все данные из словаря этого пользователя? Для этого можно воспользоваться перебором в цикле for : user.py user_0 = { 'username': 'efermi', 'first': 'enrico', 'last': 'fermi', } for key, value in user_0.items(): print("\nKey: " + key) print("Value: " + value) Как мы видим в точке , чтобы написать цикл for для словаря, необходимо создать имена для двух переменных, в которых будет храниться ключ и значение из каждой пары «ключ—значение». Этим двум переменным можно присвоить любые имена — с короткими однобуквенными именами код будет работать точно так же: for k, v in user_0.items() Вторая половина команды for в точке включает в себя имя словаря, за которым следует вызов метода items() , возвращающий список пар «ключ—значение». Цикл for сохраняет компоненты пары в двух указанных переменных. В предыдущем при- мере мы используем переменные для вывода каждого ключа v , за которым следует связанное значение w "\n" в первой команде print гарантирует, что перед каждой парой «ключ—значение» в выводе будет вставлена пустая строка: Key: last Value: fermi Key: first Value: enrico Key: username Value: efermi Снова обратите внимание на то, что пары «ключ—значение» не возвращаются в порядке их хранения даже при переборе в словаре. Python не интересует порядок Перебор словаря 109 хранения пар «ключ—значение»; отслеживаются только связи между отдельными ключами и их значениями. Перебор всех пар «ключ—значение» особенно хорошо работает для таких сло- варей, как в примере favorite_languages.py на с. 106: то есть для словарей, хра- нящих один вид информации со многими разными ключами. Перебрав словарь favorite_languages , вы получите имя каждого человека и его любимый язык программирования. Так как ключ всегда содержит имя, а значение — язык про- граммирования, в цикле вместо имен key и value используются переменные name и language . С таким выбором имен читателю кода будет проще следить за тем, что происходит в цикле: favorite_languages.py favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } for name, language in favorite_languages.items(): print(name.title() + "'s favorite language is " + language.title() + ".") Код в точке приказывает Python перебрать все пары «ключ—значение» в словаре. В процессе перебора пар ключ сохраняется в переменной name , а значение — в пере- менной language . С этими содержательными именами намного проще понять, что делает команда print в точке . Всего в нескольких строках кода выводится вся информация из опроса: Jen's favorite language is Python. Sarah's favorite language is C. Phil's favorite language is Python. Edward's favorite language is Ruby. Такой способ перебора точно так же работает и в том случае, если в словаре будут храниться результаты опроса тысяч и даже миллионов людей. Перебор всех ключей в словаре Метод keys() удобен в тех случаях, когда вы не собираетесь работать со всеми значениями в словаре. Переберем словарь favorite_languages и выведем имена всех людей, участвовавших в опросе: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } for name in favorite_languages.keys(): print(name.title()) 110 Глава 6 • Словари Строка приказывает Python извлечь из словаря favorite_languages все ключи и последовательно сохранять их в переменной name . В выходных данных представ- лены имена всех людей, участвовавших в опросе: Jen Sarah Phil Edward На самом деле перебор ключей используется по умолчанию при переборе словаря, так что этот код будет работать точно так же, как если бы вы написали for name in favorite_languages: вместо… for name in favorite_languages.keys(): Используйте явный вызов метода keys() , если вы считаете, что он упростит чтение вашего кода, — или опустите его при желании. Чтобы обратиться в цикле к значению, связанному с интересующим вас ключом, используйте текущий ключ. Для примера выведем для пары друзей сообщение о выбранном ими языке. Мы переберем имена в словаре, как это делалось ранее, но, когда имя совпадает с именем одного из друзей, программа будет выводить специальное сообщение об их любимом языке: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } friends = ['phil', 'sarah'] for name in favorite_languages.keys(): print(name.title()) if name in friends: print(" Hi " + name.title() + ", I see your favorite language is " + favorite_languages[name].title() + "!") В точке строится список друзей, для которых должно выводиться сообщение. В цикле выводится имя очередного участника опроса, а затем в точке програм- ма проверяет, входит ли текущее имя в список друзей. Если имя входит в список, выводится специальное приветствие с упоминанием выбранного языка. Чтобы получить язык в точке , мы используем имя словаря и текущее значение name как ключ. Имя выводится для всех участников, но только друзья получают еще и специальное сообщение: Edward Phil Hi Phil, I see your favorite language is Python! Sarah Перебор словаря 111 Hi Sarah, I see your favorite language is C! Jen Метод keys() также может использоваться для проверки того, участвовал ли кон- кретный человек в опросе: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } if 'erin' not in favorite_languages.keys(): print("Erin, please take our poll!") Метод keys() не ограничивается перебором: он возвращает список всех ключей, и строка просто проверяет, входит ли ключ 'erin' в список. Так как ключ в спи- ске отсутствует, программа выводит сообщение: Erin, please take our poll! Упорядоченный перебор ключей словаря Словарь всегда поддерживает связь между ключом и связанным с ним значением, но порядок получения элементов из словаря непредсказуем. Впрочем, это не со- здает проблем, потому что обычно требуется лишь получить правильное значение, связанное с каждым ключом. Один из способов получения элементов в определенном порядке основан на сор- тировке ключей, возвращаемых циклом for . Для получения упорядоченной копии ключей можно воспользоваться функцией sorted() : favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } for name in sorted(favorite_languages.keys()): print(name.title() + ", thank you for taking the poll.") Эта команда for не отличается от других команд for , если не считать того, что метод dictionary.keys() заключен в вызов функции sorted() . Эта конструкция приказывает Python выдать список всех ключей в словаре и отсортировать его перед тем, как перебирать элементы. В выводе перечислены все пользователи, участвовавшие в опросе, а их имена упорядочены по алфавиту: Edward, thank you for taking the poll. Jen, thank you for taking the poll. Phil, thank you for taking the poll. Sarah, thank you for taking the poll. 112 Глава 6 • Словари Перебор всех значений в словаре Если вас прежде всего интересуют значения, содержащиеся в словаре, используйте метод values() для получения списка значений без ключей. Допустим, вы хотите просто получить список всех языков, выбранных в опросе, и вас не интересуют имена людей, выбравших каждый язык: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } print("The following languages have been mentioned:") for language in favorite_languages.values(): print(language.title()) Команда for читает каждое значение из словаря и сохраняет его в переменной language . При выводе этих значений будет получен список всех выбранных языков: The following languages have been mentioned: Python C Python Ruby Значения извлекаются из словаря без проверки на возможные повторения. Для не- больших словарей это может быть приемлемо, но в опросах с большим количеством респондентов список будет содержать слишком много дубликатов. Чтобы получить список выбранных языков без повторений, можно воспользоваться множеством (set). Множество в целом похоже на список, но все его элементы должны быть уникальными: favorite_languages = { 'jen': 'python', 'sarah': 'c', 'edward': 'ruby', 'phil': 'python', } print("The following languages have been mentioned:") for language in set(favorite_languages.values()): print(language.title()) Когда список, содержащий дубликаты, заключается в вызов set() , Python находит уникальные элементы списка и строит множество из этих элементов. В точке set() используется для извлечения уникальных языков из favorite_languages. values() . В результате создается не содержащий дубликатов список языков про- граммирования, упомянутых участниками опроса: The following languages have been mentioned: Python C Ruby Вложение 113 В ходе дальнейшего изучения Python вы часто будете обнаруживать встроенные возможности языка, которые помогают сделать с данными именно то, что вам требуется. УПРАЖНЕНИЯ 6-4 . Глоссарий 2: теперь, когда вы знаете, как перебрать элементы словаря, упростите код из упражнения 6-3, заменив серию команд print циклом, перебирающим ключи и значения словаря . Когда вы будете уверены в том, что цикл работает, добавьте в глоссарий еще пять терминов Python . При повторном запуске программы новые слова и значения должны быть автоматически включены в вывод . 6-5 . Реки: создайте словарь с тремя большими реками и странами, по которым протекает каждая река . Одна из возможных пар «ключ—значение» — ‘nile’: ‘egypt’ . • Используйте цикл для вывода сообщения с упоминанием реки и страны — например, «The Nile runs through Egypt .» • Используйте цикл для вывода названия каждой реки, включенной в словарь . • Используйте цикл для вывода названия каждой страны, включенной в словарь . 6-6 . Опрос: Возьмите за основу код favorite_languages .py (с . 106) . • Создайте список людей, которые должны участвовать в опросе по поводу любимо- го языка программирования . Включите некоторые имена, которые уже присутствуют в списке, и некоторые имена, которых в списке еще нет . • Переберите список людей, которые должны участвовать в опросе . Если они уже прош- ли опрос, выведите сообщение с благодарностью за участие . Если они еще не про- ходили опрос, выведите сообщение с предложением принять участие . Вложение Иногда нужно сохранить множество словарей в списке или сохранить спи- сок как значение элемента словаря. Создание сложных структур такого рода называется вложением. Вы можете вложить множество словарей в список, список элементов в словарь или даже словарь внутрь другого словаря. Как наглядно показывают следующие примеры, вложение — чрезвычайно мощный механизм. Список словарей Словарь alien_0 содержит разнообразную информацию об одном пришельце, но в нем нет места для хранения информации о втором пришельце, не говоря уже о целом экране, забитом пришельцами. Как смоделировать флот вторжения? На- пример, можно создать список пришельцев, в котором каждый элемент представ- ляет собой словарь с информацией о пришельце. Следующий код строит список из трех пришельцев: aliens.py alien_0 = {'color': 'green', 'points': 5} alien_1 = {'color': 'yellow', 'points': 10} alien_2 = {'color': 'red', 'points': 15} 114 Глава 6 • Словари 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("Total number of aliens: " + str(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 Все пришельцы обладают одинаковыми характеристиками, но Python рассматри- вает каждого пришельца как отдельный объект, что позволяет изменять атрибуты каждого владельца по отдельности. Как работать с таким множеством? Представьте, что в этой игре некоторые при- шельцы изменяют цвет и начинают двигаться быстрее. Когда приходит время Вложение 115 смены цветов, мы можем воспользоваться циклом 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 elif alien['color'] == 'yellow': alien['color'] = 'red' alien['speed'] = 'fast' alien['points'] = 15 Решение с хранением словарей в списке достаточно часто встречается тогда, когда каждый словарь содержит разные атрибуты одного объекта. Например, вы можете |