Я хочу написать собственный класс, который ведет себя как dict
- так что я наследую от dict
.
Однако мой вопрос: нужно ли мне создавать закрытый dict
член в моем __init__()
методе? Я не вижу в этом смысла, так как у меня уже естьdict
поведение, если я просто наследую от dict
.
Может ли кто-нибудь указать, почему большинство фрагментов наследования выглядят так, как показано ниже?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Вместо более простого ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
На самом деле, я думаю, что я подозреваю, что ответ на вопрос состоит в том, что пользователи не могут напрямую обращаться к вашему словарю (т.е. они должны использовать методы доступа, которые вы предоставили).
Однако как насчет оператора доступа к массиву []
? Как бы это реализовать? Пока я не видел примера, показывающего, как переопределить []
оператор.
Так что если []
функция доступа не предоставляется в пользовательском классе, унаследованные базовые методы будут работать в другом словаре?
Я попробовал следующий фрагмент, чтобы проверить свое понимание наследования Python:
class myDict(dict):
def __init__(self):
self._dict = {}
def add(self, id, val):
self._dict[id] = val
md = myDict()
md.add('id', 123)
print md[id]
Получила следующую ошибку:
KeyError: <встроенный идентификатор функции>
Что не так с приведенным выше кодом?
Как мне исправить класс, myDict
чтобы я мог писать такой код?
md = myDict()
md['id'] = 123
[Редактировать]
Я отредактировал приведенный выше пример кода, чтобы избавиться от глупой ошибки, которую допустил до того, как выскочил из-за стола. Это была опечатка (я должен был заметить это по сообщению об ошибке).
источник
dict
, вам следует использовать сам объект (usingsuper
) вместо того, чтобы просто делегировать его экземпляру__dict__
- что по сути означает, что вы создаете два dicts для каждого экземпляра._dict__
все атрибуты объекта (методы, поля и т. Д.). Вы не хотите возиться с этим, если вы не хотите писать код, который сам себяКак это
Теперь вы можете использовать встроенные функции, например
dict.get()
asself.get()
.Вам не нужно заворачивать скрытое
self._dict
. Ваш класс уже является диктатом.источник
dict
без предварительного вызова его конструктора.dict
фактически содержит 2 dict-instance: 1-й - унаследованный контейнер, а 2-й - dict, содержащий атрибуты класса - вы можете избежать этого, используя слоты .__dict__
Фактически создается только при его первом обращении, так что до тех пор , как пользователи не пытаются использовать его, это прекрасно.__slots__
было бы неплохо.Для полноты, вот ссылка на документацию, упомянутую @ björn-pollex для последней версии Python 2.x (2.7.7 на момент написания):
Эмуляция типов контейнеров
(Извините за то, что не использую функцию комментариев, мне просто не разрешено делать это с помощью stackoverflow.)
источник
Проблема с этим фрагментом кода:
... в том, что ваш метод 'add' (... и любой метод, который вы хотите быть членом класса) должен иметь явное 'self', объявленное в качестве первого аргумента, например:
Чтобы реализовать перегрузку оператора для доступа к элементам по ключу, посмотрите в документации волшебные методы
__getitem__
и__setitem__
.Обратите внимание, что, поскольку Python использует Duck Typing, на самом деле может не быть причин для получения вашего пользовательского класса dict из класса dict языка - без дополнительных сведений о том, что вы пытаетесь сделать (например, если вам нужно передать экземпляр этого class в некоторый код, который не сломается, если только
isinstance(MyDict(), dict) == True
), вам может быть лучше просто реализовать API, который делает ваш класс достаточно похожим на dict, и остановиться на этом.источник
Вот альтернативное решение:
источник
Я действительно нигде не вижу правильного ответа на это
Все, что вам действительно нужно сделать, это определить свое собственное
__init__
- это все, что вам нужно.Другой пример (немного посложнее):
Этот последний пример удобен, когда вы хотите встроить какую-то логику.
В любом случае ... короче говоря
class GiveYourClassAName(dict)
, этого достаточно, чтобы ваш класс вел себя как диктатор. Любая операция dict, которую вы выполняете,self
будет ничем не хуже обычного dict.источник
Это мое лучшее решение. Я использовал это много раз.
Вы можете использовать как:
источник
Никогда не наследовать встроенный dict Python! например
update
метод не используется__setitem__
, они много делают для оптимизации. Используйте UserDict.источник