Von dict erben...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 12:58

Ich hab eine Klasse die nicht von dict erbt, aber eigentlich durch die implementieren der wichtigesten dict-Methoden, sich wie ein dict "anfühlt"... Nur, eigentlich macht es mehr Sinn von einem dict zu erben... Was mir dabei nicht gefällt, das man innerhalb der Klasse, etwas umständlich auf die Daten zugreifen muß. Das muß doch auch anders gehen.

Hier ein Beispiel:

Code: Alles auswählen

class test(dict):
    def __init__(self):
        self.data = dict #Falsch

    def test(self):
        dict.__setitem__(self, "zwei", 2)

    def test2(self):
        self.data["drei"] = 3 #Geht nicht

    def __getitem__(self, key):
        print "get item Key:", key
        return dict.__getitem__(self, key)

t = test()

t["eins"] = 1
print t["eins"]
print t

t.test()
print t

t.test2()
print t
Ich hätte eigentlich gern, das ich innerhalb der Klasse einfach mit self.data Arbeiten könnte, welches auch nur ein normales dict ist... Das geht aber nicht.

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Montag 16. Januar 2006, 13:00

Probier mal von:

http://docs.python.org/lib/module-UserDict.html

zu erben.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 16. Januar 2006, 13:06

Lösung des Problems, man nutzt UserDict, wie ich gerade im IRC erfahren hab:

Code: Alles auswählen

import UserDict

class test(UserDict.UserDict):
    def test(self):
        self.data["zwei"] = 2

t = test()

t["eins"] = 1
print t["eins"]

t.test()
print t

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
BlackJack

Montag 16. Januar 2006, 22:05

UserDict ist veraltet und nur noch aus Abwärtskompatibilität vorhanden.
jens hat geschrieben:Ich hab eine Klasse die nicht von dict erbt, aber eigentlich durch die implementieren der wichtigesten dict-Methoden, sich wie ein dict "anfühlt"... Nur, eigentlich macht es mehr Sinn von einem dict zu erben... Was mir dabei nicht gefällt, das man innerhalb der Klasse, etwas umständlich auf die Daten zugreifen muß. Das muß doch auch anders gehen.
Allerdings.
Hier ein Beispiel:

Code: Alles auswählen

class test(dict):
    def __init__(self):
        self.data = dict #Falsch

    def test(self):
        dict.__setitem__(self, "zwei", 2)

    def test2(self):
        self.data["drei"] = 3 #Geht nicht

    def __getitem__(self, key):
        print "get item Key:", key
        return dict.__getitem__(self, key)

t = test()

t["eins"] = 1
print t["eins"]
print t

t.test()
print t

t.test2()
print t
Ich hätte eigentlich gern, das ich innerhalb der Klasse einfach mit self.data Arbeiten könnte, welches auch nur ein normales dict ist... Das geht aber nicht.
Meine Güte was machst Du da für komische Sachen. Du musst nur die `__init__()` von der Klasse `dict` Aufrufen, wie bei jeder normalen Vererbung auch und dann nicht `self.data`, sondern `self` verwenden -- Deine Unterklasse *selbst* ist durch die Vererbung ein `dict`!

Code: Alles auswählen

In [25]:class MyDict(dict):
   .25.:    def __init__(self):
   .25.:        dict.__init__(self)
   .25.:        self['answer'] = 42
   .25.:

In [26]:a = MyDict()

In [27]:a
Out[27]:{'answer': 42}
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Dienstag 17. Januar 2006, 00:10

UserDict mag zwar veraltet sein, aber es gehört noch nicht zu den Modulen die ein "deprecation pending" haben. Und gerade wenn man ein dict-interface bauen will und eben einen eigenen Data-Member hat, dann ist es durchaus ab und an noch ganz gut zu gebrauchen. ;-) Behaupte ich mal so.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 17. Januar 2006, 07:30

BlackJack hat geschrieben:Meine Güte was machst Du da für komische Sachen. Du musst nur die `__init__()` von der Klasse `dict` Aufrufen, wie bei jeder normalen Vererbung auch und dann nicht `self.data`, sondern `self` verwenden -- Deine Unterklasse *selbst* ist durch die Vererbung ein `dict`!
Aha... Das vereinfacht die Sache allerdings erheblich :) Ich hatte mir das im Wikibook angesehen. Das war wohl ein Fehler...

UserDict ist eigentlich recht simple aufgebaut:
http://svn.python.org/view/python/trunk ... iew=markup

Da wir schonmal beim Thema sind: Was ist besser/effektiver? Von UserDict zu erben oder von dict selber???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Dienstag 17. Januar 2006, 11:09

Schneller ist sicherlich von dict selbst zu erben, weil alle Methoden die Du eben nicht überschreibst in C implementiert bleiben.

Einfacher ist es sicherlich von UserDict abzuleiten, weil es "angenehmer" ist ein inneres Dict-Objekt verändern zu können als sich selbst verändern zu müssen unter einigen Umständen, besonders dann wenn man nicht nur das dict()-Interface anbieten will.

Beide Wege sind in Ordnung. Soweit ich das weiß ist UserDict nirgendwo als "deprecation pending" eingestuft, das bedeutet es wird uns in der Python-Welt noch ein ganzes Stückchen begleiten, und ist vor allen Dingen auch dort verfügbar wo man noch nicht von dict() selbst ableiten kann.

--- Heiko.
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Dienstag 17. Januar 2006, 11:14

modelnine hat geschrieben:Schneller ist sicherlich von dict selbst zu erben, weil alle Methoden die Du eben nicht überschreibst in C implementiert bleiben.
Das ist allerdings ein ganz großer Pluspunkt für dict!
modelnine hat geschrieben:Soweit ich das weiß ist UserDict nirgendwo als "deprecation pending" eingestuft
Das habe ich auch nirgendwo gesehen...
modelnine hat geschrieben: und ist vor allen Dingen auch dort verfügbar wo man noch nicht von dict() selbst ableiten kann.
Warum sollte man nicht von dict ableiten können??? Zumindest sollte es ab Python 2.2 gehen...

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 17. Januar 2006, 19:14

jens hat geschrieben:Warum sollte man nicht von dict ableiten können??? Zumindest sollte es ab Python 2.2 gehen...
Ja, eben. Deswegen war es vorher nötig:
UserDict Dokumentation hat geschrieben:The need for this class has been largely supplanted by the ability to subclass directly from dict (a feature that became available starting with Python version 2.2). Prior to the introduction of dict, the UserDict class was used to create dictionary-like sub-classes that obtained new behaviors by overriding existing methods or adding new ones.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Samstag 18. November 2006, 15:37

Hab gerade festegestellt, das UserDict doch hilfreich sein kann...

Code: Alles auswählen

import UserDict

d = {"test":123}

class Preferences(UserDict.UserDict):
    def __init__(self, config_middleware):
        self.data = config_middleware

    def test(self):
        self.data["jo"]=834

p = Preferences(d)
print p
p.test()
print p

print d
Ausgaben:

Code: Alles auswählen

{'test': 123}
{'test': 123, 'jo': 834}
{'test': 123, 'jo': 834}

Diesmal möchte ich nämlich ein "externen" dict mit zusätzlichen Methoden versehen. Dabei soll aber keine kopie des dicts entstehen, sondern es soll das "selbe" dict bleiben...
Also in dem Fall ist p == d...


Auf der Seite http://docs.python.org/lib/module-UserDict.html steht auch noch was von class DictMixin(). Wozu ist das gut???

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Sonntag 19. November 2006, 00:22

jens hat geschrieben:Hab gerade festegestellt, das UserDict doch hilfreich sein kann...
Vorsicht. Dein Beispiel ist keine Kopie, sondern eine Referenz, Mach lieber so:

Code: Alles auswählen

class FooDict(dict):

    def __init__(self, data):
        self.update(data)
Und ich rate auf alle Fälle zu, dict ableiten. Das macht isinstance tests nicht kaputt.

Und wenn du wirklich das selbe Dict haben willst würde ich einfach sowas machen:

Code: Alles auswählen

class FooRefDict(object):

    def __init__(self, data):
        self._data = data
    def __getattr__(self, key):
        return getattr(self._data, key)
    def __setattr__(self, key, value):
        setattr(self._data, key, value)
UserDict liegt mir ein wenig flau im Magen, weils eine OldStyle Klasse ist und ich denen ganz gerne aus dem Weg gehe.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Montag 20. November 2006, 11:01

blackbird hat geschrieben:Vorsicht. Dein Beispiel ist keine Kopie, sondern eine Referenz
Aber genau das möchte ich ja ;)

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Antworten