Je veux écrire une classe personnalisée qui se comporte comme dict
- donc, j'hérite de dict
.
Ma question, cependant, est: Dois-je créer un dict
membre privé dans ma __init__()
méthode?. Je ne vois pas l'intérêt de cela, car j'ai déjà le dict
comportement si j'hérite simplement dict
.
Quelqu'un peut-il expliquer pourquoi la plupart des extraits d'héritage ressemblent à celui ci-dessous?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Au lieu du plus 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 que les utilisateurs ne peuvent pas accéder directement à votre dictionnaire (c'est-à-dire qu'ils doivent utiliser les méthodes d'accès que vous avez fournies).
Cependant, qu'en est-il de l'opérateur d'accès au tableau []
? Comment mettre en œuvre cela? Jusqu'à présent, je n'ai pas vu d'exemple qui montre comment remplacer l' []
opérateur.
Donc, si une []
fonction d'accès n'est pas fournie dans la classe personnalisée, les méthodes de base héritées fonctionneront sur un dictionnaire différent?
J'ai essayé l'extrait de code suivant pour tester ma compréhension de l'héritage 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]
J'ai eu l'erreur suivante:
KeyError: <id de la fonction intégrée>
Quel est le problème avec le code ci-dessus?
Comment corriger la classe myDict
pour pouvoir écrire du code comme celui-ci?
md = myDict()
md['id'] = 123
[Éditer]
J'ai modifié l'exemple de code ci-dessus pour me débarrasser de l'erreur stupide que j'ai faite avant de me précipiter loin de mon bureau. C'était une faute de frappe (j'aurais dû le repérer dans le message d'erreur).
la source
dict
- classe , vous devez utiliser l'objet lui-même (en utilisantsuper
) au lieu de simplement déléguer à l'instance__dict__
- ce qui signifie essentiellement que vous créez deux dictionnaires pour chaque instance._dict__
qui contient tous les attributs de l'objet (méthodes, champs, etc.). Vous ne voulez pas jouer avec cela à moins que vous ne vouliez écrire du code qui se modifie lui-même ...Comme ça
Vous pouvez maintenant utiliser les fonctions intégrées, telles
dict.get()
queself.get()
.Vous n'avez pas besoin d'envelopper un fichier caché
self._dict
. Votre classe est déjà un dict.la source
dict
rien d'hériter de sans appeler d'abord son constructeur.dict
contient en fait 2 dict-instance: le premier est le conteneur hérité, et le deuxième est le dict contenant les attributs de classe - vous pouvez éviter cela en utilisant des slots .__dict__
n'est en fait créé que lors de son premier accès, donc tant que les utilisateurs n'essaient pas de l'utiliser, tout va bien.__slots__
serait bien cependant.Par souci d'exhaustivité, voici le lien vers la documentation mentionnée par @ björn-pollex pour le dernier Python 2.x (2.7.7 au moment de la rédaction):
Émulation des types de conteneurs
(Désolé de ne pas utiliser la fonction de commentaires, je ne suis tout simplement pas autorisé à le faire par stackoverflow.)
la source
Le problème avec ce morceau de code:
... est que votre méthode 'add' (... et toute méthode que vous voulez être membre d'une classe) doit avoir un 'self' explicite déclaré comme premier argument, comme:
Pour implémenter la surcharge d'opérateurs pour accéder aux éléments par clé, recherchez dans la documentation les méthodes magiques
__getitem__
et__setitem__
.Notez que comme Python utilise Duck Typing, il peut en fait n'y avoir aucune raison de dériver votre classe dict personnalisée de la classe dict du langage - sans en savoir plus sur ce que vous essayez de faire (par exemple, si vous devez transmettre une instance de ceci classe dans un code quelque part qui se cassera à moins que
isinstance(MyDict(), dict) == True
), vous feriez peut-être mieux d'implémenter simplement l'API qui rend votre classe suffisamment semblable à un dict et de vous y arrêter.la source
Voici une solution alternative:
la source
Je ne vois vraiment nulle part la bonne réponse
Tout ce que vous avez à faire est de définir le vôtre
__init__
- c'est vraiment tout ce qu'il y a aussi.Un autre exemple (un peu plus complexe):
Ce dernier exemple est pratique lorsque vous souhaitez intégrer une sorte de logique.
Bref,
class GiveYourClassAName(dict)
c'est assez pour que votre classe agisse comme un dicton. Toute opération de dict que vous effectuezself
sera comme un dict normal.la source
C'est ma meilleure solution. Je l'ai utilisé plusieurs fois.
Vous pouvez utiliser comme:
la source
N'héritez jamais de dict intégré Python! par exemple, la
update
méthode n'est pas utilisée__setitem__
, ils font beaucoup pour l'optimisation. Utilisez UserDict.la source