Seite 1 von 1

Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 13:44
von theliquidwave
Hallo.
Gibt es eine Möglichkeit, einen "richtigen" Vergleich zu erstellen?
Hintergrund ist der, dass ich gerne Objekte (also Klasseninstanzen) als Keys in Dictionaries verwenden würde.

Mein Ansatz:

Code: Alles auswählen

>>> class Player(object):
    def __init__(self, x):
        self.x = x
    def __cmp__(self, other):
        return self.x != other.x

    
>>> a = Player("Peter")
>>> b = Player("Pan")
>>> c = Player("Peter")
>>> a == a
True
>>> a == b
False
>>> a == c
True
>>> b == c
False
>>> b == a
False
>>> b == b
True
>>> v = {}
>>> v[a] = 0
>>> v[b] = 1
>>> v[c] = 2
>>> v
{<__main__.Player object at 0x011DB410>: 0, <__main__.Player object at 0x011DB450>: 1, <__main__.Player object at 0x011CCBF0>: 2}
>>> v[Player("Peter")]

Traceback (most recent call last):
  File "<pyshell#33>", line 1, in <module>
    v[Player("Peter")]
KeyError: <__main__.Player object at 0x011DB4D0>
>>> 
Wie man sieht funktioniert das nicht so wie gewollt. ``v`` sollte eigentlich nur 1 und 2 beinhalten, da v[c] das v[a] überschreiben _müsste_. Es sollte außerdem möglich sein, ``v[Player("Peter")]`` aufzurufen und dann 2 zu erhalten.

Ist das ganze überhaupt so möglich?

Edit: Frage selbst beantwortet... Warum finde ich das immer erst zu spät?!

Code: Alles auswählen

>>> def hashText(text):
    h = 0
    for i, x in enumerate(text):
        h += (ord(x) + 1 << i)
    return h

>>> hashText("test")
1721
>>> hashText("tset")
1693
>>> class Player(object):
    def __init__(self, x):
        self.x = x
        self.h = hashText(x)
    def __cmp__(self, other):
        return self.x != other.x
    def __hash__(self):
        return self.h

    
>>> a = Player("Peter")
>>> b = Player("Pan")
>>> c = Player("Peter")
>>> a == a
True
>>> a == b
False
>>> a == c
True
>>> b == b
True
>>> v = {}
>>> v[a] = 0
>>> v[b] = 2
>>> v[c] = 1
>>> v
{<__main__.Player object at 0x011CC750>: 1, <__main__.Player object at 0x011CC410>: 2}
>>> v[Player("Peter")]
1
Gruß

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 14:04
von jbs
IMHO verwendest du __cmp__ etwas zweckentfremded. Warum nimmst du nicht __eq__?

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 14:07
von theliquidwave
Keine Ahnung. Mir kam nun mal intuitiv "__cmp__" in den Sinn, ohne nachzuschauen. Werde mir "__eq__" mal genauer anschauen.

Danke!

Gruß

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 14:08
von jbs
Das ist der Sinn von cmp ;)

Code: Alles auswählen

>>> cmp(1,2)
-1
>>> cmp(1,1)
0
>>> cmp(2,1)
1

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 15:21
von BlackJack
Und wo wir schon beim Sinn von eingebauten Funktionen sind: `hash()` existiert -- das braucht man sich nicht selber schreiben.

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 16:07
von theliquidwave
Tatsächliche, danke!
Weißt du zufällig wie die Funktion in der C-API heißt?

Gruß

Re: Objekte "richtig" vergleichen lassen

Verfasst: Donnerstag 23. September 2010, 16:47
von BlackJack
@Chrisber: Nein, aber es gibt da ja nicht *die* Funktion -- jeder Datentyp hat seine eigene `__hash__()`-Implementierung.