← Назад к вопросам

Какие знаешь типы словарей в Python?

1.6 Junior🔥 101 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Типы словарей в Python

Пython предлагает множество вариантов работы со словарями (словареподобными структурами). Разберём их все с примерами и рекомендациями по применению.

1. dict - обычный словарь

Стандартная реализация словаря в Python:

# Создание
user = {"name": "John", "age": 30}
user = dict(name="John", age=30)

# Особенности Python 3.7+: сохраняет порядок вставки ключей
data = {}
data["first"] = 1
data["second"] = 2
data["third"] = 3
print(list(data.keys()))  # ["first", "second", "third"]

# Операции
user["email"] = "john@example.com"  # Добавление
user.pop("age")  # Удаление с возвратом значения
user.get("phone", "No phone")  # Получение с дефолтом
user.update({"city": "NYC"})
user.setdefault("country", "USA")  # Добавить если нет

# Итерация
for key in user:
    print(key, user[key])

for key, value in user.items():
    print(key, value)

2. defaultdict - словарь с дефолтным значением

Автоматически создаёт значение для нового ключа:

from collections import defaultdict

# Создание списка для каждого ключа
student_grades = defaultdict(list)
student_grades["Alice"].append(95)
student_grades["Alice"].append(87)
student_grades["Bob"].append(92)
print(student_grades)
# defaultdict(<class "list">, {"Alice": [95, 87], "Bob": [92]})

# Подсчёт элементов
word_count = defaultdict(int)
words = ["apple", "banana", "apple", "cherry", "apple"]
for word in words:
    word_count[word] += 1
print(word_count)
# defaultdict(<class "int">, {"apple": 3, "banana": 1, "cherry": 1})

# Пользовательская функция
matrix = defaultdict(lambda: {"x": 0, "y": 0})
matrix["pos1"]["x"] = 10
print(matrix)

3. OrderedDict - упорядоченный словарь

До Python 3.7 использовался для сохранения порядка. Теперь обычный dict сохраняет порядок, но OrderedDict остаётся полезным:

from collections import OrderedDict

# Явный порядок для документирования
config = OrderedDict()
config["host"] = "localhost"
config["port"] = 5432
config["database"] = "mydb"
config["user"] = "admin"

print(list(config.keys()))  # Гарантированный порядок

# move_to_end - перемещение элементов
config.move_to_end("database")
config.move_to_end("user", last=False)  # В начало

# Полезно для LRU кэшей и упорядоченной обработки
recent_visitors = OrderedDict()
recent_visitors["user1"] = "2024-01-01"
recent_visitors["user2"] = "2024-01-02"
recent_visitors.move_to_end("user1")  # Отметить как последний

4. Counter - подсчёт элементов

Специализированный словарь для подсчётов:

from collections import Counter

# Подсчёт элементов
fruits = ["apple", "banana", "apple", "cherry", "apple", "banana"]
fruit_count = Counter(fruits)
print(fruit_count)
# Counter({"apple": 3, "banana": 2, "cherry": 1})

# Методы
fruit_count.most_common(2)  # [("apple", 3), ("banana", 2)]
fruit_count["apple"]  # 3
fruit_count["grape"]  # 0 (дефолт)

# Арифметика
fruit_count1 = Counter(["apple", "banana"])
fruit_count2 = Counter(["apple", "cherry"])

print(fruit_count1 + fruit_count2)  # Counter({"apple": 2, "banana": 1, "cherry": 1})
print(fruit_count1 - fruit_count2)  # Counter({"banana": 1})
print(fruit_count1 & fruit_count2)  # Counter({"apple": 1}) - пересечение
print(fruit_count1 | fruit_count2)  # Counter({"apple": 1, "banana": 1, "cherry": 1}) - объединение

# Анализ текста
text = "hello world hello"
char_count = Counter(text)
print(char_count.most_common(3))  # Топ 3 символа

5. ChainMap - объединение нескольких словарей

Визуальное объединение словарей без копирования:

from collections import ChainMap

# Приоритеты конфигурации
defaults = {"host": "localhost", "port": 5432, "timeout": 30}
user_config = {"host": "192.168.1.1", "port": 3306}
env_config = {"host": "prod.server.com"}

# Объединяем с приоритетом слева направо
config = ChainMap(env_config, user_config, defaults)
print(config["host"])  # prod.server.com (из env_config)
print(config["port"])  # 3306 (из user_config)
print(config["timeout"])  # 30 (из defaults)

# Изменения влияют только на первый словарь
config["new_key"] = "value"
print(env_config)  # {"host": "prod.server.com", "new_key": "value"}

# Использование в контексте
import os

local_vars = {"DEBUG": True}
chained = ChainMap(local_vars, os.environ)
print(chained.get("DEBUG"))  # True
print(chained.get("PATH"))  # Переменная окружения

6. UserDict - базовый класс для пользовательских словарей

Для создания собственных словарей с расширенной функциональностью:

from collections import UserDict

class CaseInsensitiveDict(UserDict):
    """Словарь, где ключи нечувствительны к регистру"""
    def __getitem__(self, key):
        return super().__getitem__(key.lower() if isinstance(key, str) else key)
    
    def __setitem__(self, key, value):
        key = key.lower() if isinstance(key, str) else key
        super().__setitem__(key, value)
    
    def __contains__(self, key):
        key = key.lower() if isinstance(key, str) else key
        return super().__contains__(key)

config = CaseInsensitiveDict()
config["DEBUG"] = True
print(config["debug"])  # True
print(config["DeBuG"])  # True

class ValidatedDict(UserDict):
    """Словарь с валидацией значений"""
    def __setitem__(self, key, value):
        if not isinstance(value, int):
            raise TypeError(f"Value must be int, got {type(value).__name__}")
        super().__setitem__(key, value)

scores = ValidatedDict()
scores["Alice"] = 95
# scores["Bob"] = "invalid"  # TypeError

7. WeakKeyDictionary и WeakValueDictionary

Словари со слабыми ссылками (для избежания утечек памяти):

import weakref
from weakref import WeakKeyDictionary, WeakValueDictionary

class User:
    def __init__(self, name):
        self.name = name

# WeakKeyDictionary - объект удалится, если нет других ссылок
user_cache = WeakKeyDictionary()

user1 = User("Alice")
user2 = User("Bob")

user_cache[user1] = "cached_data_1"
user_cache[user2] = "cached_data_2"

print(len(user_cache))  # 2
del user1  # Удаляем ссылку
print(len(user_cache))  # 1 - автоматически очищено

# WeakValueDictionary - значение удалится
resource_pool = WeakValueDictionary()

class Resource:
    def __init__(self, name):
        self.name = name

res1 = Resource("db_connection")
res2 = Resource("file_handle")

resource_pool["db"] = res1
resource_pool["file"] = res2

print(len(resource_pool))  # 2
del res1
print(len(resource_pool))  # 1

8. types.MappingProxyType - защищённый словарь

Реадонли вид словаря:

from types import MappingProxyType

config = {"debug": True, "port": 8000}
protected_config = MappingProxyType(config)

print(protected_config["debug"])  # True
# protected_config["debug"] = False  # TypeError: mappingproxy object does not support item assignment

# Но изменения в оригинале видны
config["debug"] = False
print(protected_config["debug"])  # False

# Полезно для приватных атрибутов класса
class Database:
    _config = MappingProxyType({"host": "localhost", "port": 5432})
    
    @classmethod
    def get_config(cls):
        return cls._config

db_config = Database.get_config()
print(db_config["host"])  # localhost
# db_config["host"] = "changed"  # TypeError

Сравнение и рекомендации

ТипИспользованиеПреимущества
dictОбщее назначениеБыстрый, встроенный, простой
defaultdictЗначения по умолчаниюАвтоматическое создание значений
OrderedDictУпорядоченностьЯвный контроль порядка, move_to_end
CounterПодсчётыВстроенная арифметика, most_common
ChainMapОбъединение со слабыми ссылкамиПриоритеты, нет копирования
UserDictКастомные словариРасширяемость, валидация
WeakKeyDictionaryКэшиАвтоматическое управление памятью
MappingProxyTypeЗащита от измененийРеадонли интерфейс

Практические примеры

# Кэш с автоматическим обнулением при удалении объекта
from weakref import WeakKeyDictionary

class Cache:
    def __init__(self):
        self._cache = WeakKeyDictionary()
    
    def set(self, obj, value):
        self._cache[obj] = value
    
    def get(self, obj):
        return self._cache.get(obj)

# Подсчёт частотности слов
from collections import Counter

def get_most_common_words(text, n=5):
    words = text.lower().split()
    word_count = Counter(words)
    return word_count.most_common(n)

# Конфигурация с дефолтами
from collections import ChainMap
import os

defaults = {"DEBUG": False, "PORT": 8000}
config = ChainMap(os.environ, defaults)

Выбор правильного типа словаря значительно упрощает и ускоряет разработку.

Какие знаешь типы словарей в Python? | PrepBro