131 votes

Une classe python qui agit comme dict

Je veux écrire une classe personnalisée qui se comporte comme dict - donc, j'hérite d' dict.

Ma question, c'est: Dois-je créer un privé dict membre dans ma __init__() méthode?. Je ne vois pas l'intérêt de ce, puisque j'ai déjà l' dict comportement, si je hériter de dict.

Quelqu'un peut-il point de savoir pourquoi la plupart de l'héritage des extraits de ressembler à celle ci-dessous?

class CustomDictOne(dict):
   def __init__(self):
      self._mydict = {} 

   # other methods follow

Au lieu de la simple...

class CustomDictTwo(dict):
   def __init__(self):
      # initialize my other stuff here ...

   # other methods follow

En fait, je pense que je soupçonne que la réponse à la question est de sorte que les utilisateurs ne peuvent pas accéder directement à votre dictionnaire (c'est à dire qu'ils ont à utiliser les méthodes d'accès que vous avez fournie).

Cependant, qu'en est l'opérateur d'accès au tableau []? Comment pourrait-on la mettre? Jusqu'à présent, je n'ai pas vu un exemple qui montre comment remplacer l' [] de l'opérateur.

Donc, si un [] accès à la fonction n'est pas fournie dans la classe personnalisée, l'héritage de la base de méthodes d'exploitation sur un autre dictionnaire?

J'ai essayé le code suivant pour tester ma compréhension de Python héritage:

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]

J'ai eu l'erreur suivante:

KeyError: < intégré dans la fonction id>

Quel est le problème avec le code ci-dessus?

Comment puis-je corriger la classe myDict , de sorte que je peux écrire du code comme celui-ci?

md = myDict()
md['id'] = 123

[Modifier]

J'ai édité l'exemple de code ci-dessus pour se débarrasser de la bête erreur que j'ai faite avant de m'enfuie de mon bureau. C'était une faute de frappe (j'aurais repéré à partir du message d'erreur).

127voto

Ricky Wilson Points 112
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 keys(self): 
        return self.__dict__.keys()

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

    def __cmp__(self, dict):
        return cmp(self.__dict__, dict)

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

    def add(self, key, value):
        self.__dict__[key] = value

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

    def __call__(self):
        return self.__dict__

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



o = Mapping()
o.foo = "bar"
o['lumberjack'] = 'foo'
o.add('a', 'b')
print 'lumberjack' in o

print o()

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

93voto

S.Lott Points 207588

Comme ça

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

Vous pouvez maintenant utiliser les fonctions intégrées, telles que dict.get() tant que self.get() .

Vous n'avez pas besoin d'envelopper un self._dict caché. Votre classe est déjà un dictée.

46voto

Björn Pollex Points 41424

Consultez la documentation sur l' émulation des types de conteneur . Dans votre cas, le premier paramètre à add devrait être self .

9voto

he1ix Points 103

Par souci d’exhaustivité, voici le lien vers la documentation mentionnée par @ björn-pollex pour la dernière version de Python 2.x (2.7.7 au moment de la rédaction):

Émulation de types de conteneurs

(Désolé de ne pas utiliser la fonction de commentaires, je ne suis pas autorisé à le faire par stackoverflow.)

2voto

bgporter Points 11119

Le problème avec ce bout de code:

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

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


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

...est-ce que votre "ajouter" de la méthode (...et de toute méthode que vous voulez être un membre d'une classe) doit avoir un explicite " moi " a déclaré que son premier argument, comme:

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

Pour mettre en œuvre la surcharge d'opérateur d'accès aux éléments clés, regardez dans les docs pour les méthodes magiques __getitem__ et __setitem__.

Notez que parce que Python utilise le Duck-Typing, il y aura peut-être aucune raison de tirer votre personnalisé dict classe à partir de la langue du dict classe -- sans en savoir plus sur ce que vous essayez de faire e.g, si vous avez besoin de passer une instance de cette classe dans un peu de code quelque part qui va casser à moins d' isinstance(MyDict(), dict) == True), vous pourriez être mieux mise en œuvre de l'API qui rend votre classe suffisamment dict et de s'y arrêter.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X