Класс python, который действует как dict



я хочу создать пользовательский класс, который ведет себя как 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


[Edit]



я отредактировал пример кода выше, чтобы избавиться от глупой ошибки, которую я сделал, прежде чем я бросился прочь от моего стола. Это была опечатка (я должен был заметить ее из сообщения об ошибке).

1677   5  

5 ответов:

проверьте документацию на эмуляция типов контейнеров. В вашем случае, первый параметр add должно быть self.

class Mapping(dict):

    def __setitem__(self, key, item):
        self.__dict__[key] = item

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

    def __repr__(self):
        return repr(self.__dict__)

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

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

    def clear(self):
        return self.__dict__.clear()

    def copy(self):
        return self.__dict__.copy()

    def has_key(self, k):
        return k in self.__dict__

    def update(self, *args, **kwargs):
        return self.__dict__.update(*args, **kwargs)

    def keys(self):
        return self.__dict__.keys()

    def values(self):
        return self.__dict__.values()

    def items(self):
        return self.__dict__.items()

    def pop(self, *args):
        return self.__dict__.pop(*args)

    def __cmp__(self, dict_):
        return self.__cmp__(self.__dict__, dict_)

    def __contains__(self, item):
        return item in self.__dict__

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

    def __unicode__(self):
        return unicode(repr(self.__dict__))


o = Mapping()
o.foo = "bar"
o['lumberjack'] = 'foo'
o.update({'a': 'b'}, c=44)
print 'lumberjack' in o
print o

In [187]: run mapping.py
True
{'a': 'b', 'lumberjack': 'foo', 'foo': 'bar', 'c': 44}

такой

class CustomDictOne(dict):
   def __init__(self,*arg,**kw):
      super(CustomDictOne, self).__init__(*arg, **kw)

теперь вы можете использовать встроенные функции, такие как dict.get() как self.get().

вам не нужно обернуть скрытый self._dict. Ваш класс уже и в дикт.

для полноты картины, вот ссылка на документацию, упомянутую @björn-pollex для последней версии Python 2.x (2.7.7 на момент написания статьи):

Эмуляция Типов Контейнеров

(Извините, что не использую функцию комментариев, мне просто не разрешено делать это с помощью stackoverflow.)

проблема с этим куском кода:

class myDict(dict):
    def __init__(self):
        self._dict = {}

    def add(id, val):
        self._dict[id] = val


md = myDict()
md.add('id', 123)

...это ваш метод "добавить" (...и любой метод, который вы хотите быть членом класса) должен иметь явное "я", объявленное в качестве его первого аргумента, например:

def add(self, 'id', 23):

чтобы реализовать перегрузку оператора для доступа к элементам по ключу, посмотрите в docs для магических методов __getitem__ и __setitem__.

обратите внимание, что поскольку Python использует Утиный ввод, на самом деле может не быть причин выведите свой пользовательский класс dict из класса dict языка - не зная больше о том, что вы пытаетесь сделать (например, если вам нужно передать экземпляр этого класса в какой-то код где-то, что сломается, если isinstance(MyDict(), dict) == True), вам может быть лучше просто реализовать API, который делает ваш класс достаточно дикт-подобным и останавливается там.

Comments

    Ничего не найдено.