Ich möchte eine benutzerdefinierte Klasse schreiben, die sich wie dict
folgt verhält - also erbe ich von dict
.
Meine Frage lautet jedoch: Muss ich dict
in meiner __init__()
Methode ein privates Mitglied erstellen ? Ich verstehe den Sinn davon nicht, da ich das dict
Verhalten bereits habe, wenn ich einfach von erbe dict
.
Kann jemand darauf hinweisen, warum die meisten Vererbungsschnipsel wie die folgenden aussehen?
class CustomDictOne(dict):
def __init__(self):
self._mydict = {}
# other methods follow
Anstelle der einfacheren ...
class CustomDictTwo(dict):
def __init__(self):
# initialize my other stuff here ...
# other methods follow
Ich glaube, ich vermute, dass die Antwort auf die Frage so ist, dass Benutzer nicht direkt auf Ihr Wörterbuch zugreifen können (dh sie müssen die von Ihnen angegebenen Zugriffsmethoden verwenden).
Was ist jedoch mit dem Array-Zugriffsoperator []
? Wie würde man das umsetzen? Bisher habe ich kein Beispiel gesehen, das zeigt, wie der []
Operator überschrieben wird .
Wenn []
in der benutzerdefinierten Klasse keine Zugriffsfunktion bereitgestellt wird, arbeiten die geerbten Basismethoden mit einem anderen Wörterbuch.
Ich habe das folgende Snippet ausprobiert, um mein Verständnis der Python-Vererbung zu testen:
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]
Ich habe folgenden Fehler erhalten:
KeyError: <integrierte Funktions-ID>
Was ist mit dem obigen Code falsch?
Wie korrigiere ich die Klasse, myDict
damit ich solchen Code schreiben kann?
md = myDict()
md['id'] = 123
[Bearbeiten]
Ich habe das obige Codebeispiel bearbeitet, um den dummen Fehler zu beseitigen, den ich gemacht habe, bevor ich von meinem Schreibtisch weggerannt bin. Es war ein Tippfehler (ich hätte ihn anhand der Fehlermeldung erkennen sollen).
quelle
dict
, sollten Sie das Objekt selbst verwenden (usingsuper
), anstatt es einfach an die Instanz zu delegieren.__dict__
Dies bedeutet im Wesentlichen, dass Sie für jede Instanz zwei Diktate erstellen._dict__
das alle Objektattribute (Methoden, Felder usw.) enthält. Sie möchten nicht damit herumspielen, es sei denn, Sie möchten Code schreiben, der sich selbstSo was
Jetzt können Sie die integrierten Funktionen wie
dict.get()
as verwendenself.get()
.Sie müssen kein verstecktes verpacken
self._dict
. Ihre Klasse bereits ist ein dict.quelle
dict
ohne zuerst den Konstruktor aufzurufen.dict
Objekt tatsächlich zwei Diktatinstanzen enthält: Das erste ist der geerbte Container und das zweite ist das Diktat, das die Klassenattribute enthält. Sie können dies vermeiden, indem Sie Slots verwenden .__dict__
wird eigentlich nur beim ersten Zugriff erstellt. Solange Benutzer nicht versuchen, es zu verwenden, ist es in Ordnung.__slots__
wäre aber schön.Der Vollständigkeit halber hier der Link zu der Dokumentation, die von @ björn-pollex für das neueste Python 2.x (2.7.7 zum Zeitpunkt des Schreibens) erwähnt wurde:
Containertypen emulieren
(Entschuldigung, dass Sie die Kommentarfunktion nicht verwenden. Ich darf dies nur nicht durch Stackoverflow tun.)
quelle
Das Problem mit diesem Codestück:
... ist, dass Ihre 'add'-Methode (... und jede Methode, die Sie Mitglied einer Klasse werden möchten) ein explizites' self 'als erstes Argument deklarieren muss, wie:
Um die Überladung des Operators für den Zugriff auf Elemente per Schlüssel zu implementieren, suchen Sie in den Dokumenten nach den magischen Methoden
__getitem__
und__setitem__
.Da Python Duck Typing verwendet, gibt es möglicherweise keinen Grund, Ihre benutzerdefinierte Diktatklasse aus der Diktatklasse der Sprache abzuleiten - ohne mehr darüber zu wissen, was Sie tun möchten (z. B. wenn Sie eine Instanz davon übergeben müssen Klasse in einen Code an einem Ort, der kaputt geht, es sei denn
isinstance(MyDict(), dict) == True
), ist es möglicherweise besser, nur die API zu implementieren, die Ihre Klasse ausreichend diktiert und dort stoppt.quelle
Hier ist eine alternative Lösung:
quelle
Ich sehe wirklich nirgendwo die richtige Antwort darauf
Alles, was Sie wirklich tun müssen, ist, Ihre eigenen zu definieren
__init__
- das ist wirklich alles, was es auch gibt.Ein weiteres Beispiel (etwas komplexer):
Dieses letzte Beispiel ist praktisch, wenn Sie eine Art Logik einbetten möchten.
Wie auch immer ... kurz gesagt,
class GiveYourClassAName(dict)
es reicht aus, um Ihre Klasse wie ein Diktat zu verhalten. Jede Diktieroperation, die Sie ausführen, istself
wie ein reguläres Diktat.quelle
Das ist meine beste Lösung. Ich habe das oft benutzt.
Sie können wie folgt verwenden:
quelle
Erben Sie niemals von dem in Python integrierten Diktat! Zum Beispiel wird die
update
Methode nicht verwendet__setitem__
, sie trägt viel zur Optimierung bei. Verwenden Sie UserDict.quelle