Seite 1 von 1

Von dict erben...

Verfasst: Montag 16. Januar 2006, 12:58
von jens
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.

Verfasst: Montag 16. Januar 2006, 13:00
von modelnine
Probier mal von:

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

zu erben.

--- Heiko.

Verfasst: Montag 16. Januar 2006, 13:06
von jens
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

Re: Von dict erben...

Verfasst: Montag 16. Januar 2006, 22:05
von BlackJack
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}

Verfasst: Dienstag 17. Januar 2006, 00:10
von modelnine
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.

Re: Von dict erben...

Verfasst: Dienstag 17. Januar 2006, 07:30
von jens
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???

Verfasst: Dienstag 17. Januar 2006, 11:09
von modelnine
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.

Verfasst: Dienstag 17. Januar 2006, 11:14
von jens
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...

Verfasst: Dienstag 17. Januar 2006, 19:14
von Leonidas
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.

Verfasst: Samstag 18. November 2006, 15:37
von jens
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???

Verfasst: Sonntag 19. November 2006, 00:22
von mitsuhiko
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.

Verfasst: Montag 20. November 2006, 11:01
von jens
blackbird hat geschrieben:Vorsicht. Dein Beispiel ist keine Kopie, sondern eine Referenz
Aber genau das möchte ich ja ;)