Prüfen, ob ein gleiches Objekt in einem set ist

18/06/2008 - 11:28 von Frederik | Report spam
Hallo!

Vor kurzem bin ich auf einen Unterschied zwischen set und list in der
Überprüfung von enthaltenen Objekten gestoßen. Wenn ich "x in list"
teste, wird für die enthaltenen Objekte __eq__ bzw. __cmp__
aufgerufen. Wenn dies True ergibt, ist auch der Test True. Wenn ich "x
in set" teste, funktioniert das nicht. Im IRC habe ich schon den
Hinweis erhalten, dass set wohl zunàchst __hash__ vergleicht, und nur
bei gleichen Werten __eq__ bzw. __cmp__ aufruft.

Nun habe ich eine Reihe von Instanzen einer eigenen Klasse, die recht
komplizierte Prüfungen für __eq__ implementiert. Ich möchte nun
testen, ob ein set eine nach diesen Regeln gleiche Instanz bereits
enthàlt. Mir sind zwei Ansàtze eingefallen: Entweder ist teste "x in
list(set)". Das ist aber irgendwie unsauber und auch recht langsam.
Oder ich implementiere __hash__ für meine Klasse, und gebe immer den
gleichen Wert zurück, damit in der Folge __eq__ getestet wird. Das
wàre aber eigentlich ein Missbrauch von __hash__.

Nun würde ich gerne wissen, wie ihr dieses Problem lösen würdet.
Vielleicht gibt es ja auch noch sauberere Lösungen, die mir nicht
einfallen.

Danke und liebe Grüße
Frederik
 

Lesen sie die antworten

#1 Diez B. Roggisch
18/06/2008 - 11:36 | Warnen spam
Frederik wrote:

Hallo!

Vor kurzem bin ich auf einen Unterschied zwischen set und list in der
Überprüfung von enthaltenen Objekten gestoßen. Wenn ich "x in list"
teste, wird für die enthaltenen Objekte __eq__ bzw. __cmp__
aufgerufen. Wenn dies True ergibt, ist auch der Test True. Wenn ich "x
in set" teste, funktioniert das nicht. Im IRC habe ich schon den
Hinweis erhalten, dass set wohl zunàchst __hash__ vergleicht, und nur
bei gleichen Werten __eq__ bzw. __cmp__ aufruft.

Nun habe ich eine Reihe von Instanzen einer eigenen Klasse, die recht
komplizierte Prüfungen für __eq__ implementiert. Ich möchte nun
testen, ob ein set eine nach diesen Regeln gleiche Instanz bereits
enthàlt. Mir sind zwei Ansàtze eingefallen: Entweder ist teste "x in
list(set)". Das ist aber irgendwie unsauber und auch recht langsam.
Oder ich implementiere __hash__ für meine Klasse, und gebe immer den
gleichen Wert zurück, damit in der Folge __eq__ getestet wird. Das
wàre aber eigentlich ein Missbrauch von __hash__.

Nun würde ich gerne wissen, wie ihr dieses Problem lösen würdet.
Vielleicht gibt es ja auch noch sauberere Lösungen, die mir nicht
einfallen.




In dem Moment wo du __hash__ immer auf den selben Wert bringst ist die
Performance von list() und set() gleich - denn es muss immer jedes Element
verglichen werden.

Ohne mehr ueber deine Domaenen-Objekte zu wissen kann man wenig sagen - aber
normalerweise implementiert man __hash__ so, das gilt:

a == b => hash(a) == hash(b)

Solange diese Bedingung nicht verletzt ist, kannst du zB einen hash ueber
bestimmte attribute als string concateniert oder so bilden.

Wie gesagt - dazu muesstest du schonmal zeigen, was da so in deinen
Objekten "abgeht".

Diez

Ähnliche fragen