Ответ
Чтобы объект вел себя как словарь (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-объект, не плюнет тебе в лицо, а примет как родного.