Подтвердить что ты не робот

Подкласс dict: UserDict, dict или ABC?

В чем разница между UserDict, dict и ABC и какой из них рекомендуется? Документы, похоже, обесценивают UserDict?

Также кажется, что UserDict update() будет использовать мой метод setitem, тогда как dict нет? Какие методы действительно необходимы для переопределения данных? Я хочу использовать функции setitem и getitem?

С ABC мне придется реализовать абсолютно все методы, поскольку он не предусматривает реализацию по умолчанию?

Я хочу сделать dict, что делает две вещи:

  • intern() все ключи и значения
  • сохранить некоторые значения в базе данных SQLite

Итак, какие из UserDict, dict и ABC лучше всего позволили бы мне это сделать?

4b9b3361

Ответ 1

Если вы хотите, чтобы пользовательская коллекция фактически хранила данные, подкласс dict. Это особенно полезно, если вы хотите расширить интерфейс (например, добавить методы).

Ни один из встроенных методов не вызовет ваш пользовательский __getitem__/__setitem__. Если вам нужен полный контроль над ними, создайте собственный класс, который вместо этого будет использовать абстрактный базовый класс collections.MutableMapping.

ABC не предоставляет средства для хранения фактических данных, а только для интерфейса с реализациями по умолчанию для некоторых методов. Однако эти реализации по умолчанию будут вызывать ваши пользовательские __getitem__ и __setitem__. Вам нужно будет использовать внутренний dict для хранения данных и реализовать все абстрактные методы: __len__, __iter__, __getitem__, __setitem__ и __delitem__.

Класс UserDict из модуля collections (в Python 2, модуль также называется UserDict) - это оболочка вокруг внутреннего dict, реализующая MutableMapping ABC. Если вы хотите настроить поведение dict, эта реализация может быть отправной точкой.

Вкратце:

  • MutableMapping определяет интерфейс. Подкласс, чтобы создать что-то, что действует как dict. Это полностью зависит от вас, если и как вы храните данные.
  • UserDict - это реализация MutableMapping с использованием внутреннего "реального" dict в качестве хранилища. Если вы хотите иметь подобную дискету хранения, но переопределите некоторые методы, выставленные dict, это может быть хорошей отправной точкой для вас. Но обязательно прочитайте код, чтобы узнать, как реализуются основные методы, чтобы вы были совместимы при переопределении метода.
  • dict - это "настоящая вещь". Подкласс это, если вы хотите расширить интерфейс. Переопределение методов для создания пользовательских вещей может быть опасным, так как обычно есть несколько способов доступа к данным, и вы можете получить несогласованный API.

Ответ 2

Не используйте класс UserDict - он вам не нужен. Как говорят документы, вы можете просто подклассифицировать dict напрямую.

Однако вам все еще нужен модуль UserDict для DictMixin:

Примечание. DictMixin, но не официально устаревший, был удален в Python 3 и рекомендуется в документах, которые вы используете collections.MutableMapping. Это, однако, имеет недостаток - вам нужно реализовать больше интерфейса словаря - __delitem__, __getitem__, __iter__, __len__ и __setitem__. С помощью DictMixin вы можете просто реализовать те, которые хотите изменить, а остальные использовать реализацию по умолчанию.

from UserDict import DictMixin

class MyDict(DictMixin, dict):
    def __setitem__(self, key, value):
        print key, value # just an example
        # use intern(key) or whatever here
        dict.__setitem__(self, key, value) # or
        # super(MyDict, self).__setitem__(key, value)

m = MyDict()

m['a'] = 'b'
# a b
m.update({'a': 'c'})
# a c

Он автоматически сделает update использующим __setitem__, как вы хотите.