Что такое словарь dict в Python: очень быстро про методы с примерами

Продолжаем учить змеиный язык

Что такое словарь dict в Python: очень быстро про методы с примерами

Агония, злость и бессонные ночи — вот что ждёт python-разработчика, который не знает, что такое словари, но работает с базами данных. Нет, словари не переводят змеиный язык на русский, но помогают эффективнее и удобнее обрабатывать много информации в коде. Как с ними работать, разберёмся в этой статье.

Что такое словарь dict в Python

Определение словаря dict

Словари в Python — это структура данных, которая хранит информацию в виде пары: «ключ: значение». Прямо как в бумажных словарях или записных книжках.

user = {"name": "Алексей", "age": 25}
# Выведет: Алексей
print(user["name"])

Словари Python реализованы на основе хеш-таблиц — системы, где данные хранятся по точным адресам. Если простыми словами, то при обращении по ключу интерпретатор вычисляет хеш ключа (программно преобразует его в уникальное число). Это число работает как конкретный указатель на ячейку в памяти. Поэтому Python напрямую находит нужное значение — без долгого перебора всех остальных элементов по очереди. За счёт этого прямой поиск срабатывает моментально.

Главные особенности словарей в Python:

  • Поиск по ключам: чтобы найти нужное значение, не надо вспоминать его числовой индекс, достаточно вспомнить имя ключа.
  • Уникальность: ключи в одном словаре не повторяются, если добавить два одинаковых ключа, Python будет учитывать значение только последнего.
  • Строгие ключи и любые значения: ключом словаря может быть только неизменяемый (hashable) объект: строка, число или кортеж. Список и другой словарь ключом быть не могут — Python выбросит TypeError. А вот значением при этом может быть что угодно.
  • Изменяемость: можно изменять значения, добавлять новые пары ключ-значение и удалять существующие.

Чем словарь отличается от списка и кортежа

Что такое списки и кортежи

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

tasks = ["помыть посуду", "написать код"]

Кортежи — это тоже набор данных, которые организованы по очереди. Их синтаксис очень похож на списки:

tasks = ("помыть посуду", "написать код")

Кортежи в отличие от списков нельзя изменять. Например, не получится заменить значение “помыть посуду”, на “постирать вещи”.

Чем списки и кортежи отличаются от словарей в Python

Главное отличие словарей от списков и кортежей заключается в способе обращения к значениям. Чтобы достать значение из кортежа или списка, нужно знать его индекс — порядок, в котором это значение идёт. Счёт индекса всегда начинается с нуля.

# создаём список покупок
shopping_list = ["Молоко", "Хлеб", "Яблоки", "Сыр"]
# достаём второй элемент из списка по индексу 1
second_item = shopping_list[1]
# выводим результат на экран
print("Вторая покупка в списке:", second_item)

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

# создаём словарь с ценами на продукты
shop_prices = {"Молоко": 100, "Хлеб": 50, "Яблоки": 120}
# узнаём цену хлеба по его ключу-названию
bread_price = shop_prices["Хлеб"]
# выводим цену на экран
print("Цена хлеба:", bread_price)

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

# создаём базу ноутбуков, где ключ — название, а значение — характеристики
laptops_base = {"MacBook Air M1": "8 ГБ ОЗУ, 256 ГБ SSD", "ThinkPad X1": "16 ГБ ОЗУ, 512 ГБ SSD"}
# получаем данные конкретной модели по её названию
macbook_specs = laptops_base["MacBook Air M1"]
# выводим характеристики нужного ноутбука
print("Характеристики Apple:", macbook_specs)

Как создать словарь в Python

Словарь создаётся тремя способами: литералом {}, встроенной функцией dict() или методом dict.fromkeys() — последний удобен, когда нужно инициализировать сразу несколько ключей с одинаковым значением.

Полезный блок со скидкой

Если тема зашла и хочется разобраться, как устроено всё остальное в Python, — держите промокод Практикума на любой платный курс: KOD (можно просто нажать). Он даст скидку при покупке и позволит сэкономить на обучении.

Бесплатные курсы в Практикуме тоже есть — по всем специальностям и направлениям, начать можно в любой момент, карту привязывать не нужно, если что.

Создание через литерал {}

Чаще всего словари создают через литерал {}, для этого нужно написать название словаря, поставить равно, в фигурных скобках написать ключи и, через двоеточие, их значения.

# создаём базовый профиль пользователя
user_profile = {
    "name": "Алексей",
    "age": 25,
    "city": "Москва"
}
# выводим профиль на экран
print("Карточка пользователя:", user_profile)

Технически пары ключ — значение, можно писать в одну строку, но на практике так редко делают. Лучше расположить элементы в виде списка, так код будет более читаемым.

Создание через dict()

Второй способ собрать словарь — использовать функцию dict(). Для этого нужно написать название словаря, объявить функцию и внутри неё написать пары ключ — значение.

# создаём такой же профиль, но уже с помощью функции
user_profile = dict(name="Алексей", age=25, city="Москва")
# выводим профиль на экран
print("Карточка пользователя:", user_profile)

Функцию dict() редко используют для создания словарей с нуля. Она создаёт ключи, которые:

  • Состоят только из букв, цифр и нижнего подчёркивания.
  • Не начинаются с цифр.
  • Не содержат пробелов.

При использовании литерала {} таких ограничений нет, там можно использовать любые неизменяемые типы данных для создания ключей, даже кортежи.

Ещё, чтобы создать словарь через dict() Python должен найти эту функцию в памяти, подготовить к запуску и только потом собрать данные. Это влияет на скорость работы.

В-третьих, запись через {} визуально более понятная и очень похожа на JSON — популярный у разработчиков формат записи данных.

Функцию dict() используют, когда нужно создать словарь уже из готового набора данных.

# получаем данные профиля в виде списка пар из другой системы
profile_data = [("name", "Алексей"), ("age", 25), ("city", "Москва")]
# превращаем этот список в полноценный словарь
user_profile = dict(profile_data)
# выводим получившийся словарь
print("Карточка пользователя:", user_profile)

Создание через метод dict.fromkeys()

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

Например, мы открываем кафе и заводим систему учёта столиков. Утром они все пустые, поэтому нам нужно массово присвоить им статус «свободен». Передаём методу dict.fromkeys() список ключей и дефолтное значение:

# список всех столиков в нашем кафе
tables = ["стол_1", "стол_2", "стол_3"]
# создаём словарь, где каждому столику сразу присваивается нужный статус
cafe_status = dict.fromkeys(tables, "свободен")
# проверяем результат выведя готовый словарь на экран
print("Начальные статусы:", cafe_status)

Создание пустого словаря в Python

Пустые словари создаются так же, как и заполненные, через литерал, либо через функцию dict().

# создаём пустую корзину для покупок в интернет-магазине
empty_cart = {}
# создаём пустую корзину, с помощью функции
empty_cart = dict()

Создание из списков с помощью zip()

Словарь из списка можно сделать вручную, но это неудобно. Проще использовать функцию zip() вместе с уже знакомым dict().

Zip() работает как молния, она берёт элементы из двух списков и объединяет их попарно: первый объединяется с первым, второй со вторым и так далее. Потом функция dict() превращает эти пары в ключи и значения.

# создаём список с названиями напитков
drinks = ["Эспрессо", "Капучино", "Латте"]
# создаём отдельный список с ценами на эти напитки
prices = [100, 150, 170]
# сшиваем списки вместе и превращаем результат в словарь
cafe_menu = dict(zip(drinks, prices))
# выводим меню на экран
print("Меню кофейни:", cafe_menu)

Как обратиться к элементам словаря

Как обратиться по ключу: [] и .get()

Создать словарь — обычно только половина дела. Надо правильно достать из него нужные данные. Для этого существует два способа: по ключу и через метод .get().

Как достать значения по ключу

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

# создаём словарь с характеристиками смартфона
smartphone = {"brand": "Apple", "model": "iPhone 13", "storage": 256}
# получаем название бренда по ключу
phone_brand = smartphone["brand"]
# выводим результат на экран
print("Бренд смартфона:", phone_brand)

Этот способ работает, только если в словаре есть нужный ключ. Если его нет, то Python выдаст ошибку KeyError.

Как достать значение через .get()

Чтобы скрипт не ломался из-за отсутствующего ключа, можно использовать метод .get().

Если ключ есть, .get() вернёт его значение. А если ключа нет, метод не будет вызывать ошибку, а вернёт специальный объект None.

# словарь со смартфоном
smartphone = {"brand": "Apple", "model": "iPhone 13", "storage": 256}
# ищем информацию о влагозащите с помощью безопасного метода
water_protection = smartphone.get("waterproof")
# выводим результат поиска, ошибки не будет (вернётся None)
print("Влагозащита:", water_protection)

Вместо None в методе .get() можно указать другое значение для вывода по умолчанию.

# словарь со смартфоном
smartphone = {"brand": "Apple", "model": "iPhone 13", "storage": 256}
# пытаемся узнать цвет устройства, а если его нет, ставим чёрный по умолчанию
phone_color = smartphone.get("color", "чёрный")
# выводим цвет на экран
print("Цвет смартфона:", phone_color)

Перебор элементов при помощи методов .keys(), .values(), .items() в Python

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

Для таких случаев в Python есть 3 метода, которые часто используют в связке с циклом for:

.keys() — перебирает ключи.

# создаём словарь с оценками учеников
student_grades = {"Алиса": 5, "Борис": 4, "Виктор": 5}
# перебираем только имена учеников, то есть ключи
for name in student_grades.keys():
    # выводим каждое имя на экран
    print("Имя ученика:", name)

.values() — собирает только значения.

# создаём корзину покупок с ценами
shopping_cart = {"Книга": 500, "Ручка": 100, "Тетрадь": 150}
# заводим переменную для подсчёта общей суммы
total_sum = 0
# перебираем только цены товаров
for price in shopping_cart.values():
    # прибавляем текущую цену к общей сумме
    total_sum = total_sum + price
# выводим итоговую сумму на экран
print("Итого к оплате:", total_sum)

.items() — отдаёт сразу и ключи, и значения.

# создаём базу пользователей с их ролями
users_roles = {"Иван": "админ", "Анна": "редактор", "Петр": "читатель"}
# перебираем сразу имена и роли
for name, role in users_roles.items():
    # выводим данные о каждом пользователе
    print("Пользователь:", name, "Роль:", role)

Основные методы словарей Python

get() и setdefault(): безопасное получение значения

Мы уже разобрали метод get(), который позволяет безопасно получать значения из словаря по ключу, если ключа нет, то программа вернёт значение None, но не ошибку.

Кроме .get() в Python есть ещё один метод .setdefault(). Он тоже безопасно возвращает значение, но это не единственная его функция. Если нужного ключа в словаре нет, .setdefault() возвращает значение по умолчанию и добавляет в словарь новый ключ с этим значением.

# создаём профиль нового сотрудника без указания его отдела
employee = {"name": "Алиса", "position": "стажёр"}
# ищем отдел, а если ключа нет, назначаем отдел стажировки и сразу сохраняем в словарь
department = employee.setdefault("department", "стажировка")
# выводим полученное значение отдела
print("Отдел сотрудника:", department)
# выводим весь профиль, чтобы убедиться, что новый ключ добавился в словарь
print("Обновлённый профиль:", employee)

Этот метод полезен, когда нужно обработать много данных и заполнить пропущенные поля стандартными значениями.

update(): обновление и слияние словарей в Python

Представьте, что у вас есть заполненный профиль пользователя в базе данных, но информацию в нём надо дополнить, например, указать город, обновить место работы. Для таких случаев есть метод .update().

Он может массово добавить в словарь новые элементы. Если ключ новый, метод добавит его в словарь, если старый, то перезапишет значение на новое.

# создаём профиль пользователя
user_profile = {"name": "Виктор", "job": "стажёр"}
# обновляем старую должность и добавляем новый ключ с городом
user_profile.update({"job": "разработчик", "city": "Казань"})
# выводим изменённый профиль на экран
print("Обновлённый профиль:", user_profile)

Ещё метод .update() позволяет объединять два словаря в один.

# берём профиль пользователя
user_profile = {"name": "Виктор", "job": "разработчик", "city": "Казань"}
# создаём отдельный словарь с контактными данными
contact_info = {"email": "vic@mail.ru", "phone": "555-1234"}
# сливаем словарь с контактами в основной профиль
user_profile.update(contact_info)
# выводим объединённый профиль со всеми данными
print("Полный профиль пользователя:", user_profile)

pop() и del: удаление элементов

Чтобы убрать элемент из словаря, в Python используют оператор del, либо метод .pop().

Оператор del — это встроенная команда языка, поэтому она пишется без скобок и точек. Вы указываете словарь и ключ, Python удаляет этот ключ с его значением.

# создаём корзину покупок с товарами и их ценами
shopping_cart = {"Книга": 500, "Закладка": 50, "Ручка": 100}
# удаляем закладку из корзины с помощью оператора del
del shopping_cart["Закладка"]
# выводим обновлённую корзину на экран
print("Корзина после удаления:", shopping_cart)

Использовать del надо осторожно, если удалить ключ, которого нет в словаре, программа упадёт с ошибкой KeyError.

Метод .pop() тоже удаляет ключ и значение словаря, но сохраняет это значение в переменную, которую можно отдельно вызвать.

# берём корзину покупок
shopping_cart = {"Книга": 500, "Закладка": 50, "Ручка": 100}
# выкладываем ручку из корзины и сохраняем её цену в переменную
removed_price = shopping_cart.pop("Ручка")
# выводим цену удалённого товара на экран
print("Цена удалённого товара:", removed_price)
# проверяем, что товар действительно пропал из корзины
print("Оставшиеся товары:", shopping_cart)

Ещё метод .pop() безопаснее, ему можно прописать значение по умолчанию, если вы решите удалить ключ, которого нет, то программа не упадёт, а вернёт это значение.

# создаём корзину покупок
shopping_cart = {"Книга": 500, "Закладка": 50, "Ручка": 100}
# пытаемся удалить блокнот, а если его нет в корзине, возвращаем ноль
notebook_price = shopping_cart.pop("Блокнот", 0)
# выводим результат безопасного удаления
print("Цена удалённого блокнота:", notebook_price)
# выводим корзину, чтобы показать, что она не сломалась и не изменилась
print("Состояние корзины:", shopping_cart)

copy() и deepcopy(): копирование словаря

Допустим, нам надо сделать копию словаря. Для этого можно создать новую переменную и приравнять её к словарю.

# создаём базовые характеристики героя в игре
hero_stats = {"health": 100, "speed": 10}
# пытаемся скопировать их для второго героя через знак равно
second_hero = hero_stats
# выводим результат, чтобы увидеть словарь второго героя
print("Характеристики второго героя:", second_hero)

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

Чтобы создать независимую копию словаря, лучше использовать метод .copy(). Он дублирует данные из оригинального словаря в другой участок памяти, поэтому копия не влияет на оригинал.

# создаём стартовые характеристики героя
hero_stats = {"health": 100, "speed": 10}
# делаем независимую копию с помощью метода
second_hero = hero_stats.copy()
# второй герой получает урон от монстра
second_hero["health"] = 50
# выводим данные первого героя и видим, что он не пострадал
print("Состояние первого героя:", hero_stats)
print("Состояние второго героя:", second_hero)

Но у метода copy() есть недостаток, если в словаре лежат другие словари, списки, множества, то copy() по-прежнему создаёт ссылку на эти данные в памяти, а не копирует их в новый участок.

Для словарей, которые содержат списки и другие словари, есть функция copy.deepcopy(). Она создаёт в памяти такой же набор данных, как и в списке/словаре.

# подключаем специальный модуль Python для глубокого копирования
import copy
# создаём профиль героя с вложенным списком предметов в рюкзаке
hero_profile = {"name": "Артур", "backpack": ["меч", "зелье"]}
# делаем полную копию профиля вместе со списком предметов
second_hero = copy.deepcopy(hero_profile)
# второй герой подбирает щит и кладёт его в свой рюкзак
second_hero["backpack"].append("щит")
# проверяем рюкзаки и видим, что щит появился только у второго героя
print("Рюкзак первого героя:", hero_profile["backpack"])
print("Рюкзак второго героя:", second_hero["backpack"])

Функция copy.deepcopy() находит и дублирует все вложенные значения, вместо того чтобы просто создать ссылку на них в памяти. Из-за этого она работает медленнее, чем .copy().

clear(): очистка словаря

Если нужно не просто удалить пару элементов, а стереть все данные, то есть метод .clear(). Он удаляет из словаря все пары ключ — значение.

# создаём корзину с товарами перед оформлением заказа
shopping_cart = {"Книга": 500, "Закладка": 50, "Ручка": 100}
# пользователь оплатил заказ, поэтому полностью очищаем корзину
shopping_cart.clear()
# выводим корзину на экран, чтобы убедиться, что она стала пустой
print("Корзина после оплаты:", shopping_cart)

Как добавить и изменить элемент в словарь Python

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

# создаём словарь с текущим заказом в кофейне
cafe_order = {"coffee": "Латте", "price": 200}
# гость попросил добавить десерт, записываем его по новому ключу
cafe_order["dessert"] = "Чизкейк"
# выводим заказ на экран, чтобы увидеть новое блюдо
print("Заказ после добавления десерта:", cafe_order)

Изменить существующее значение можно точно так же. Пишем название словаря, ключ и новое значение.

# берём наш изначальный заказ с кофе
cafe_order = {"coffee": "Латте", "price": 200}
# гость передумал и попросил капучино, перезаписываем значение по старому ключу
cafe_order["coffee"] = "Капучино"
# выводим обновлённый заказ
print("Изменённый заказ:", cafe_order)

Если нужно добавить или изменить много значений, то можно воспользоваться уже знакомым методом .update().

Пример кода с добавлением ключей и значений через .update().

# создаём базовый заказ гостя
cafe_order = {"coffee": "Латте", "price": 200}
# массово добавляем в заказ сироп и номер столика
cafe_order.update({"syrup": "Карамель", "table": 5})
# выводим заказ со всеми новыми данными
print("Расширенный заказ:", cafe_order)

Пример кода с изменением значений.

# берём заказ, в котором уже указаны напиток и цена
cafe_order = {"coffee": "Латте", "price": 200}
# гость решил взять простой эспрессо, поэтому обновляем сразу и напиток, и цену
cafe_order.update({"coffee": "Эспрессо", "price": 150})
# выводим итоговый заказ
print("Обновлённый заказ:", cafe_order)

Практические примеры использования dict

Мы познакомились с основной теорией, самое время открыть среду разработки и попрактиковаться с кодом на примере простой RPG игры.

Пример 1 — подсчёт частоты элементов

Представим, что нам надо подсчитать лут в рюкзаке героя. Сделать это можно при помощи словаря. Для этого создадим инвентарь, пройдёмся по списку вещей и посчитаем каждую.

# список предметов, которые выпали из монстров
dropped_loot = ['зелье', 'монета', 'меч', 'зелье', 'монета', 'монета']
# создаём пустой словарь для инвентаря героя
inventory = {}
# перебираем каждый найденный предмет по очереди
for item in dropped_loot:
    # если такой предмет уже лежит в инвентаре — просто прибавляем единицу
    if item in inventory:
        inventory[item] += 1
    # если предмета ещё нет — кладём его и записываем, что он у нас один
    else:
        inventory[item] = 1
# выводим результат на экран
print(inventory)

Результат

Практические примеры использования dict

Пример 2 — словарь как конфиг приложения

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

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

# создаём словарь со стартовыми настройками игры
game_config = {
    'difficulty': 'normal',
    'volume': 80,
    'fullscreen': True
}
# игра запускается, проверяем уровень сложности, чтобы создать правильных врагов
print("Сложность:", game_config['difficulty'])
# допустим, игрок зашёл в меню и убавил музыку
game_config['volume'] = 30
# проверяем, что настройки звука обновились
print("Громкость:", game_config['volume'])

Результат

Практические примеры использования dict

Пример 3 — инвертирование словаря

В играх предметы часто хранятся под уникальными внутренними номерами — ID. Этот номер можно представить как ключ, а предмет, к которому он относится значением.

Но игроки обычно видят только названия предметов. Если надо реализовать функцию поиска предмета по инвентарю, то интуитивно будет искать по названию, не по ID.

Для этого можно вывернуть словарь наизнанку, названия предметов превратить в ключи, а ID в значения.

# база данных предметов: ID -> название
item_database = {
    'itm_001': 'ржавый меч',
    'itm_002': 'зелье здоровья',
    'itm_003': 'деревянный щит'
}
# создаём пустой словарь для поиска по названию: название -> ID
name_to_id = {}
# перебираем ID и названия из базы
for item_id, name in item_database.items():
    # меняем их местами и записываем в новый словарь
    name_to_id[name] = item_id
# смотрим, как выглядит вывернутый наизнанку словарь
print("Словарь для поиска:", name_to_id)
# проверяем, какой ID у зелья здоровья
print("ID для предмета 'зелье здоровья':", name_to_id['зелье здоровья'])

Результат.

Практические примеры использования dict

Пример 4 — вложенный словарь

Вложенный словарь — словарь в котором хранятся другие словари, списки, кортежи, множества. Эта логика похожа на папку, внутри которой много других папок.

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

# создаём профиль нашего персонажа
hero_profile = {
    'name': 'Артур',
    'stats': {
        'health': 100,
        'mana': 50
    },
    'equipment': {
        'weapon': 'ржавый меч',
        'armor': 'старая куртка'
    }
}
# смотрим, как зовут героя
print("Имя героя:", hero_profile['name'])
# достаём значение из вложенного словаря: сначала обращаемся к экипировке, а затем к оружию
print("Текущее оружие:", hero_profile['equipment']['weapon'])
# герой получил урон, уменьшаем здоровье во вложенном словаре на 20
hero_profile['stats']['health'] -= 20
# проверяем, сколько здоровья осталось
print("Осталось здоровья:", hero_profile['stats']['health'])

Результат.

Практические примеры использования dict

Пример 5 — dict comprehension

Иногда нам нужно взять старый словарь, изменить в нём все значения по какому-то правилу и собрать из этого новый словарь.

Допустим, торговец в игре решил устроить «чёрную пятницу» и сделать скидку 50% на все свои товары. Чтобы изменить словарь с ценами, мы можем воспользоваться конструкцией dict comprehensio.

По сути, это блок с циклом for, который пишется в строку и устроен следующим образом: {ключ: новое_значение for ключ, значение in старый_словарь.items()}.

# старые цены у торговца
old_prices = {
    'ржавый меч': 100,
    'зелье здоровья': 50,
    'деревянный щит': 150
}
# создаём новый словарь, берём каждый предмет, а его цену делим на 2
sale_prices = {item: price // 2 for item, price in old_prices.items()}
# смотрим, что получилось
print("Черная пятница! Новые цены:", sale_prices)

Результат

Практические примеры использования dict

Сравнение словаря с другими структурами данных

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

Пример словаря

# создаём словарь с ценами на сладости
candy_prices = {"Карамель": 50, "Шоколад": 120, "Ириска": 70}
# достаём цену шоколада по его ключу-названию
chocolate_price = candy_prices["Шоколад"]
# выводим цену на экран
print("Цена шоколада:", chocolate_price)

Пимер списка

# собираем список конфет, которые хотим съесть друг за другом
candy_list = ["Карамель", "Шоколад", "Карамель"]
# достаём первую конфету по индексу ноль
first_candy = candy_list[0]
# выводим результат на экран
print("Первая конфета:", first_candy)

Пример кортежа

# задаём неизменяемые размеры подарочной коробки для конфет
box_sizes = (15, 20, 10)
# получаем ширину коробки по индексу
box_width = box_sizes[1]
# выводим ширину на экран
print("Ширина коробки:", box_width)

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

# складываем в пакет разные конфеты, специально добавляя два шоколада
candy_bag = {"Шоколад", "Карамель", "Шоколад", "Ириска"}
# выводим содержимое на экран и видим, что дубликат шоколада исчез
print("Уникальные вкусы в пакете:", candy_bag)

Множества отличаются от списков и кортежей тем, что у них нет числового индекса и каждое значение уникально. Это значит, что вызвать конкретное значение или добавить несколько одинаковых не получится. Если приводить аналогию, множества похожи на пакет с конфетами, где каждая конфета уникальна и просто беспорядочно лежит среди других конфет.

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

ХарактеристикаСписок (list)Кортеж (tuple)Множество (set)Словарь (dict)
Синтаксис[a, b, c](a, b, c){a, b, c}{k1: v1, k2: v2}
УпорядоченностьДа (индексы)Да (индексы)НетДа (с версии Python 3.7+)
ИзменяемостьИзменяемыйНеизменяемыйИзменяемоеИзменяемый
ДубликатыРазрешеныРазрешеныУникальныУникальные ключи, дубли значений
ДоступПо индексуПо индексуТолько перебор/поискПо ключу
Когда использоватьДля хранения очередей и данных, где важен строгий порядок (история, списки задач).Для фиксированных наборов данных, которые нельзя случайно перезаписать (координаты, константы).Для удаления дубликатов из других коллекций и быстрого поиска уникальных элементов.Для связи данных парами и быстрого поиска значений по конкретному идентификатору.

Типичные ошибки при работе со словарями в Python

1. Обращение к несуществующему ключу (KeyError)

Если запросить у словаря значение по ключу, которого в нём нет, Python остановит программу с ошибкой KeyError.

# создаём список бронирований, где ключ — номер столика, а значение — имя гостя
reservations = {"Столик 1": "Иван", "Столик 3": "Анна"}
# пытаемся узнать, кто сидит за пятым столиком, программа падает с ошибкой KeyError
guest = reservations["Столик 5"]
# выводим имя гостя на экран (вывод не сработает из-за ошибки)
print("Гость за пятым столиком:", guest)

Чтобы подстраховаться, можно использовать метод .get(). Если ключа нет, он вернёт значение None или дефолтное значение, которое вы зададите.

# используем тот же список бронирований
reservations = {"Столик 1": "Иван", "Столик 3": "Анна"}
# безопасно проверяем пятый столик, если брони нет — возвращаем статус «свободен»
guest = reservations.get("Столик 5", "свободен")
# выводим статус пятого столика, программа успешно продолжает работу
print("Статус пятого столика:", guest)

2. Изменяемые типы данных в качестве ключа (TypeError)

Ключом может быть только то, что нельзя изменить после создания, например, строки, числа, логические значения и кортежи. А вот списки и другие словари — нет. Если попытаться сделать ключом список, появится ошибка Type Error (unhashable type).

# объединяем двух гостей в список, чтобы посадить их за один столик
couple = ["Иван", "Анна"]
# заводим пустой словарь для особых пожеланий от столиков
special_requests = {}
# пытаемся использовать список как ключ, но получаем ошибку TypeError (unhashable type)
special_requests[couple] = "Торт со свечами"
# выводим пожелания на экран (из-за ошибки вывода не будет)
print("Особые пожелания:", special_requests)

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

# объединяем гостей в неизменяемый кортеж с помощью круглых скобок
couple = ("Иван", "Анна")
# снова заводим пустой словарь для особых пожеланий
special_requests = {}
# используем кортеж как ключ, теперь Python всё пропускает без ошибок
special_requests[couple] = "Торт со свечами"
# выводим пожелания на экран
print("Особые пожелания:", special_requests)

3. Удаление элементов прямо во время цикла (RuntimeError)

Нельзя удалять или добавлять элементы в словарь в тот момент, когда вы перебираете его обычным циклом for. Размеры словаря в памяти меняются на ходу, Python путается и выдаёт RuntimeError.

# создаём словарь со статусом оплаты счетов для разных столиков
bills_status = {"Столик 1": "оплачен", "Столик 2": "ожидает", "Столик 3": "оплачен"}
# перебираем столики и их статусы
for table, status in bills_status.items():
    # если счёт оплачен, пытаемся закрыть этот столик
    if status == "оплачен":
        # удаляем столик прямо во время цикла и получаем RuntimeError
        del bills_status[table]
# выводим оставшиеся неоплаченные счета (из-за ошибки вывода не будет)
print("Неоплаченные счета:", bills_status)

Чтобы избежать ошибки, можно перебирать не сам словарь, а список его ключей. Тогда программа будет идти по фиксированному списку, а удалять элементы из самого словаря.

# берём тот же словарь со счетами
bills_status = {"Столик 1": "оплачен", "Столик 2": "ожидает", "Столик 3": "оплачен"}
# превращаем ключи словаря в отдельный список и перебираем только его
for table in list(bills_status.keys()):
    # проверяем статус каждого столика через оригинальный словарь
    if bills_status[table] == "оплачен":
        # безопасно удаляем оплаченный столик
        del bills_status[table]
# выводим результат, программа отработала и оставила только один неоплаченный счёт
print("Неоплаченные счета:", bills_status)

Советуем дополнительно почитать по теме:

Бонус для читателей

Если вам интересно погрузиться в мир ИТ и при этом немного сэкономить, держите наш промокод на курсы Практикума. Он даст вам скидку при оплате, поможет с льготной ипотекой и даст безлимит на маркетплейсах. Ладно, окей, это просто скидка, без остального, но хорошая.

Вам может быть интересно
easy