Какие специальные методы Python нужно реализовать для эмуляции поведения словаря?

Ответ

Чтобы объект вел себя как словарь (mapping), он должен реализовывать протокол контейнера. Лучшей практикой является наследование от абстрактного базового класса collections.abc.MutableMapping.

Этот подход требует реализации всего пяти обязательных методов, а остальные (keys, values, items, get, __contains__ и др.) предоставляются автоматически.

Обязательные методы для MutableMapping:

  • __getitem__(self, key): для доступа по ключу (obj[key]).
  • __setitem__(self, key, value): для присвоения значения (obj[key] = value).
  • __delitem__(self, key): для удаления элемента (del obj[key]).
  • __iter__(self): для итерации по ключам (for key in obj).
  • __len__(self): для получения размера (len(obj)).

Пример реализации:

from collections.abc import MutableMapping

class DictLike(MutableMapping):
    def __init__(self, *args, **kwargs):
        # Внутреннее хранилище
        self._storage = dict(*args, **kwargs)

    def __getitem__(self, key):
        return self._storage[key]

    def __setitem__(self, key, value):
        print(f"Установка значения для ключа '{key}'")
        self._storage[key] = value

    def __delitem__(self, key):
        del self._storage[key]

    def __iter__(self):
        return iter(self._storage)

    def __len__(self):
        return len(self._storage)

# Использование
d = DictLike()
d['name'] = 'Alice' # Установка значения для ключа 'name'

print(d['name'])      # Вывод: Alice
print('name' in d)    # Вывод: True (метод __contains__ работает автоматически)
print(list(d.keys())) # Вывод: ['name'] (метод keys() тоже)

Наследование от MutableMapping гарантирует, что ваш класс будет соответствовать стандартному интерфейсу словаря и будет совместим с другими компонентами Python, ожидающими mapping-объект.

Ответ 18+ 🔞

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

Чтобы твой объект вел себя как нормальный словарь, а не как какая-то мартышлюшка, ему нужно реализовать протокол контейнера. Самый правильный и лёгкий путь — наследоваться от абстрактного базового класса collections.abc.MutableMapping.

Весь прикол в том, что от тебя требуют всего пять обязательных методов, а остальная куча полезных штук (keys, values, items, get, __contains__ и прочая хуета) прилетает тебе на блюдечке с голубой каёмочкой, автоматом.

Вот эти пять священных методов для MutableMapping:

  • __getitem__(self, key): Чтобы доставать по ключу, типа obj[key].
  • __setitem__(self, key, value): Чтобы пихать значение, типа obj[key] = value.
  • __delitem__(self, key): Чтобы удалять нахуй, типа del obj[key].
  • __iter__(self): Чтобы по ключам итерироваться, типа for key in obj.
  • __len__(self): Чтобы размер узнать, типа len(obj).

Смотри, как это выглядит на практике:

from collections.abc import MutableMapping

class DictLike(MutableMapping):
    def __init__(self, *args, **kwargs):
        # Внутреннее хранилище, где вся магия и происходит
        self._storage = dict(*args, **kwargs)

    def __getitem__(self, key):
        return self._storage[key]

    def __setitem__(self, key, value):
        print(f"Установка значения для ключа '{key}'")
        self._storage[key] = value

    def __delitem__(self, key):
        del self._storage[key]

    def __iter__(self):
        return iter(self._storage)

    def __len__(self):
        return len(self._storage)

# Использование
d = DictLike()
d['name'] = 'Alice' # Установка значения для ключа 'name'

print(d['name'])      # Вывод: Alice
print('name' in d)    # Вывод: True (метод __contains__ работает автоматически, ёпта!)
print(list(d.keys())) # Вывод: ['name'] (метод keys() тоже, охуеть!)

Когда ты наследуешься от MutableMapping, ты как бы даёшь честное пионерское, что твой класс будет вести себя как словарь. И тогда весь остальной Python-мир, который ждёт mapping-объект, не плюнет тебе в лицо, а примет как родного.