Комментарии (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)
Выбор правильного типа словаря значительно упрощает и ускоряет разработку.