Какие ограничения есть у словаря (dict) в Python?

Ответ

Основные ограничения и особенности словарей (dict) в Python:

  1. Хешируемость ключей. Ключом может быть только неизменяемый (immutable) и хешируемый объект: int, float, str, tuple (если все его элементы тоже хешируемы), frozenset. Списки, другие словари и множества (set) — недопустимы.

    # Работает
    d1 = {1: 'a', 'key': 2, (3, 4): 'tuple', frozenset([5,6]): 'set'}
    
    # Вызовет TypeError: unhashable type
    d2 = {[1, 2]: 'list'}  # Список
    d3 = {{'a': 1}: 'dict'} # Словарь
  2. Гарантированный порядок. Начиная с Python 3.7 (официальная спецификация), словари сохраняют порядок вставки элементов. В Python 3.6 это было деталью реализации CPython.

  3. Уникальность ключей. Повторное присваивание значения по существующему ключу перезаписывает старое значение.

  4. Производительность. Операции поиска, вставки и удаления в среднем имеют сложность O(1), но в худшем случае (из-за коллизий хешей) могут деградировать до O(n).

  5. Потребление памяти. Словари из-за внутренней хеш-таблицы занимают значительно больше памяти, чем списки (list) или кортежи (tuple) с тем же количеством элементов. Это важный фактор при работе с большими объемами данных в памяти.

  6. Изменяемость. Словарь — изменяемый (mutable) тип. Это требует осторожности при использовании словарей как ключей к другим словарям (нельзя) или как значений по умолчанию в аргументах функций (известная проблема).

Ответ 18+ 🔞

А, слушай-ка, про словари в питоне. Ну, это ж, блядь, основа основ, но там такие подводные камни, что мама не горюй. Ёпта, разберём по косточкам, чтобы потом не вышло, как с Герасимом и Муму.

Первое и главное — ключи, сука. Ключом может быть только объект, который не меняется и который можно посчитать, как там... хешировать, блядь. То есть числа, строки, кортежи (если внутри них тоже всё прилично), frozenset. А вот если ты туда сунешь список или другой словарь — пиши пропало, получишь TypeError: unhashable type. Пиздец и точка.

# Так можно, всё пристойно
d1 = {1: 'a', 'key': 2, (3, 4): 'tuple', frozenset([5,6]): 'set'}

# А вот так — нет, получишь по ебалу от интерпретатора
d2 = {[1, 2]: 'list'}  # Список? Нахуй!
d3 = {{'a': 1}: 'dict'} # Словарь как ключ? Да ты охуел!

Второе — порядок. Раньше, блядь, была вакханалия, они там как хотели, так и лежали. А теперь, с Python 3.7, порядок вставки гарантированно сохраняется. Как положил, так и лежит. Удобно, чё.

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

Четвёртое — скорость. В основном всё быстро, O(1), то есть почти мгновенно. Но если совсем не повезёт с коллизиями хешей, то может и до O(n) скатиться, то есть тормозить начнёт конкретно. Но это редкость, ёпта.

Пятое — память. Вот это, блядь, важный момент! Словари — они прожорливые, как мартышлюшка. Места жрут овердохуища по сравнению со списками или кортежами. Если данных дохуя — задумайся, а оно тебе надо?

Шестое — изменяемость. Словарь — он как хитрая жопа, всё время меняется. Из-за этого его, сука, нельзя использовать как ключ в другом словаре (помнишь первый пункт?). И ещё есть классическая ловушка — не используй словарь как значение по умолчанию в аргументах функции! А то все вызовы будут тырить один и тот же словарь, и будет пиздец, неразбериха и волнение ебать.

Вот, вроде и всё основное. Запомнил? Главное — ключи должны быть хешируемыми, а то будет тебе unhashable type в сраку.