Identity Dictionary / Set in Python?

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
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mittwoch 2. Januar 2008, 13:09

Normale dicts/sets in Python speichern Objekte basierend auf __hash__ und __eq__ bzw. __cmp__. Insbesondere kann man keine Listen als Schlüssel benutzen, da diese "unhashable" sind. Manchmal will man aber die Objektidentität als Schlüssel benutzen, z.B. wenn ich prüfen will, ob ich ein Objekt bereits verarbeitet habe - egal ob es __eq__ zu einem anderen ist oder nicht.

Gibt's da etwas Fertiges für Python?

Für ein identityset habe ich folgenden Vorschlag:

Code: Alles auswählen

class identityset(dict):
    def add(self, obj): self[id(obj)] = obj
    def __iter__(self): return self.itervalues()
d.h., ich nutzt id(obj) als Schlüssel - in der Hoffnung, das ist jeweils eine einzigartige Zahl. Ich muss mir das Objekt selbst merken, damit es mir nicht bei einer GC abhanden kommt. Für ein identitydict könnte man vielleicht sowas benutzen:

Code: Alles auswählen

class identitydict(dict):
    def __getitem__(self, obj): return self[id(obj)][1]
    def __setitem__(self, obj, value): self[id(obj)] = (obj, value)
Ich möchte mir aber nicht die Arbeit einer vollständigen Implementierung machen (zudem ich gar nicht wüsste, wie ich das pickle-bar hinbekomme), wenn das andere schon für mich gemacht haben ;)

Stefan
windner
User
Beiträge: 76
Registriert: Freitag 19. Oktober 2007, 11:25

Mittwoch 2. Januar 2008, 14:09

d.h., ich nutzt id(obj) als Schlüssel - in der Hoffnung, das ist jeweils eine einzigartige Zahl.
Ist einzigartig. Wenn's nur darum geht, zu prüfen, ob a in b ist, würde ich eben dieses benutzen.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Mittwoch 2. Januar 2008, 15:10

windler, das geht nicht. Siehe z.B.

Code: Alles auswählen

a = [1]
b = [1]
assert a is not b
c = [a]
assert b not in c
AssertionError
Auch der "in"-Operator geht nicht über die Identität der Objekte.

Stefan
Antworten