Part 5

Словарь

Списки могут быть удобны во многих ситуациях, но они ограничены тем, что к элементам обращаются через индексы: 0, 1, 2 и так далее. Если вы хотите найти какой-то элемент в списке, вам нужно либо знать его индекс, либо, в худшем случае, пройти по всему списку.

Еще одна центральная структура данных в Python — словарь. В словаре элементы индексируются ключами. Каждый ключ соответствует значению. Значения, хранящиеся в словаре, можно получать и изменять с помощью ключа.

Использование словаря

Следующий пример показывает, как работает структура данных словарь. Вот простой словарь с финского на английский:

my_dictionary = {}

my_dictionary["apina"] = "monkey"
my_dictionary["banaani"] = "banana"
my_dictionary["cembalo"] = "harpsichord"

print(len(my_dictionary))
print(my_dictionary)
print(my_dictionary["apina"])
Пример вывода

3 {'apina': 'monkey', 'banaani': 'banana', 'cembalo': 'harpsichord'} monkey

Запись {} создает пустой словарь, в который теперь можно добавить содержимое. Добавляются три пары ключ-значение: "apina" соответствует "monkey", "banaani" соответствует "banana", а "cembalo" соответствует "harpsichord". В конце выводится количество пар ключ-значение в словаре, весь словарь и значение, связанное с ключом "apina".

После определения словаря мы также могли бы использовать его с пользовательским вводом:

word = input("Please type in a word: ")
if word in my_dictionary:
    print("Translation: ", my_dictionary[word])
else:
    print("Word not found")

Обратите внимание на использование оператора in выше. Когда он применяется к переменной типа словарь, он проверяет, находится ли первый операнд среди ключей, хранящихся в словаре. При разных вводах эта программа может вывести следующее:

Пример вывода

Please type in a word: apina Translation: monkey

Пример вывода

Please type in a word: pöllö Word not found

Что можно хранить в словаре?

Тип данных называется словарем, но он не обязан содержать только строки. Например, в следующем словаре ключи — строки, а значения — целые числа:

results = {}
results["Mary"] = 4
results["Alice"] = 5
results["Larry"] = 2

Здесь ключи — целые числа, а значения — списки:

lists = {}
lists[5] = [1, 2, 3]
lists[42] = [5, 4, 5, 4, 5]
lists[100] = [5, 2, 3]

Как работают ключи и значения

Каждый ключ может появиться в словаре только один раз. Если вы добавите запись с ключом, который уже существует в словаре, исходное значение, связанное с этим ключом, будет заменено новым значением:

my_dictionary["suuri"] = "big"
my_dictionary["suuri"] = "large"
print(my_dictionary["suuri"])
Пример вывода

large

Все ключи в словаре должны быть неизменяемыми. Поэтому список нельзя использовать как ключ, потому что его можно изменить. Например, выполнение следующего кода вызывает ошибку:

my_dictionary[[1, 2, 3]] = 5
Пример вывода

TypeError: unhashable type: 'list'

В отличие от ключей, значения, хранящиеся в словаре, могут изменяться, поэтому в качестве значения подходит любой тип данных. Одно и то же значение также может быть связано с несколькими ключами в одном словаре.

Loading
Loading

Обход словаря

Знакомый цикл for item in collection можно использовать и для обхода словаря. Если использовать его напрямую со словарем, цикл проходит по ключам, хранящимся в словаре, один за другим. В следующем примере выводятся все ключи и значения, хранящиеся в словаре:

my_dictionary = {}

my_dictionary["apina"] = "monkey"
my_dictionary["banaani"] = "banana"
my_dictionary["cembalo"] = "harpsichord"

for key in my_dictionary:
    print("key:", key)
    print("value:", my_dictionary[key])
Пример вывода

key: apina value: monkey key: banaani value: banana key: cembalo value: harpsichord

Иногда нужно пройти по всему содержимому словаря. Метод items возвращает все ключи и значения, хранящиеся в словаре, по одной паре за раз:


for key, value in my_dictionary.items():
    print("key:", key)
    print("value:", value)

В примерах выше вы могли заметить, что ключи обрабатываются в том же порядке, в котором они были добавлены в словарь. Поскольку ключи обрабатываются на основе хеш-значения, порядок обычно не должен иметь значения в приложениях. На самом деле во многих старых версиях Python порядок не гарантированно соответствует времени добавления.

Несколько более продвинутых способов использовать словари

Рассмотрим список слов:

word_list = [
  "banana", "milk", "beer", "cheese", "sourmilk", "juice", "sausage",
  "tomato", "cucumber", "butter", "margarine", "cheese", "sausage",
  "beer", "sourmilk", "sourmilk", "butter", "beer", "chocolate"
]

Мы хотели бы анализировать этот список слов разными способами. Например, хотели бы знать, сколько раз каждое слово встречается в списке.

Словарь может быть полезным инструментом для управления такой информацией. В примере ниже мы проходим по элементам списка один за другим. Используя слова из списка как ключи в новом словаре, мы связываем с каждым ключом количество раз, которое слово встречалось:

def counts(my_list):
    words = {}
    for word in my_list:
        # if the word is not yet in the dictionary, initialize the value to zero
        if word not in words:
            words[word] = 0
        # increment the value
        words[word] += 1
    return words

# call the function
print(counts(word_list))

Программа выводит следующее:

Пример вывода

{'banana': 1, 'milk': 1, 'beer': 3, 'cheese': 2, 'sourmilk': 3, 'juice': 1, 'sausage': 2, 'tomato': 1, 'cucumber': 1, 'butter': 2, 'margarine': 1, 'chocolate': 1}

А что если мы хотим классифицировать слова по первой букве каждого слова? Один способ сделать это — использовать словари:

def categorize_by_initial(my_list):
    groups = {}
    for word in my_list:
        initial = word[0]
        # initialize a new list when the letter is first encountered
        if initial not in groups:
            groups[initial] = []
        # add the word to the appropriate list
        groups[initial].append(word)
    return groups

groups = categorize_by_initial(word_list)

for key, value in groups.items():
    print(f"words beginning with {key}:")
    for word in value:
        print(word)

Структура функции очень похожа на предыдущее упражнение, но на этот раз значениями, связанными с ключами, являются списки. Программа выводит следующее:

Пример вывода

words beginning with b: banana beer butter beer butter beer words beginning with m: milk margarine words beginning with c: cheese cucumber cheese chocolate words beginning with s: sourmilk sausage sausage sourmilk sourmilk words beginning with j: juice words beginning with t: tomato

Loading
Loading
Loading

Удаление ключей и значений из словаря

Разумеется, пары ключ-значение из словаря тоже можно удалять. Есть два способа сделать это. Первый — команда del:

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
del staff["David"]
print(staff)
Пример вывода

{'Alan': 'lecturer', 'Emily': 'professor'}

Если попытаться использовать команду del для удаления ключа, которого нет в словаре, возникнет ошибка:

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
del staff["Paul"]
Пример вывода
>>> del staff["Paul"]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'Paul'

Поэтому перед удалением ключа нужно проверить, присутствует ли он в словаре:

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
if "Paul" in staff:
  del staff["Paul"]
  print("Deleted")
else:
  print("This person is not a staff member")

Другой способ удалять записи из словаря — метод pop:

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
deleted = staff.pop("David")
print(staff)
print(deleted, "deleted")
Пример вывода

{'Alan': 'lecturer', 'Emily': 'professor'} lecturer deleted

Как видно выше, pop также возвращает значение из удаленной записи.

По умолчанию pop тоже вызывает ошибку, если попытаться удалить ключ, которого нет в словаре. Этого можно избежать, передав методу второй аргумент, который содержит значение возврата по умолчанию. Это значение возвращается, если ключ не найден в словаре. Здесь подойдет специальное значение Python None:

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
deleted = staff.pop("Paul", None)
if deleted == None:
  print("This person is not a staff member")
else:
  print(deleted, "deleted")
Пример вывода

This person is not a staff member

Обратите внимание: если вам нужно удалить содержимое всего словаря и вы попытаетесь сделать это циклом for, например так

staff = {"Alan": "lecturer", "Emily": "professor", "David": "lecturer"}
for key in staff:
  del staff[key]

вы получите сообщение об ошибке:

Пример вывода

RuntimeError: dictionary changed size during iteration

При обходе коллекции циклом for ее содержимое не должно изменяться во время выполнения цикла.

К счастью, для этой цели есть метод словаря:

staff.clear()
Loading
Loading

Использование словарей для структурированных данных

Словари очень полезны для структурирования данных. Следующий код создаст словарь, содержащий некоторые персональные данные:

person = {"name": "Pippa Python", "height": 154, "weight": 61, "age": 44}

Это означает, что у нас есть человек по имени Pippa Python, рост которого 154, вес 61 и возраст 44. Ту же информацию можно было бы хранить в переменных:

name = "Pippa Python"
height = 154
weight = 61
age = 44

Преимущество словаря в том, что это коллекция. Он собирает связанные данные в одной переменной, поэтому легко получать доступ к разным компонентам. Такое же преимущество дает список:

person = ["Pippa Python", 153, 61, 44]

При использовании списков программист должен помнить, что хранится по каждому индексу списка. Ничто не указывает, что person[2] содержит вес, а person[3] — возраст человека. При использовании словаря этой проблемы нет, потому что к каждому фрагменту данных обращаются через именованный ключ.

Предположим, мы определили нескольких людей в одном и том же формате. Тогда мы можем получить доступ к их данным следующим образом:

person1 = {"name": "Pippa Python", "height": 154, "weight": 61, "age": 44}
person2 = {"name": "Peter Pythons", "height": 174, "weight": 103, "age": 31}
person3 = {"name": "Pedro Python", "height": 191, "weight": 71, "age": 14}

people = [person1, person2, person3]

for person in people:
    print(person["name"])

combined_height = 0
for person in people:
    combined_height += person["height"]

print("The average height is", combined_height / len(people))
Пример вывода

Pippa Python Peter Pythons Pedro Python The average height is 173.0

Loading
Loading

На этом этапе курса вы можете выбрать участие в исследовании, связанном с обучением программированию. Участие добровольное, и отдельных участников нельзя будет идентифицировать по данным, собранным в исследовании. Вы можете свободно выйти из эксперимента в любой момент. Нажмите здесь, чтобы начать исследование!

Вы дошли до конца этого раздела! Перейти к следующему разделу:

Текущие баллы можно посмотреть в синем индикаторе в правом нижнем углу страницы.

В этой части:
  1. 1. Дополнительные списки

  2. 2. Ссылки

  3. 3. Словарь

  4. 4. Кортеж