Objekte "richtig" vergleichen lassen

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
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

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ß
Grüßle.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

IMHO verwendest du __cmp__ etwas zweckentfremded. Warum nimmst du nicht __eq__?
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Keine Ahnung. Mir kam nun mal intuitiv "__cmp__" in den Sinn, ohne nachzuschauen. Werde mir "__eq__" mal genauer anschauen.

Danke!

Gruß
Grüßle.
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Das ist der Sinn von cmp ;)

Code: Alles auswählen

>>> cmp(1,2)
-1
>>> cmp(1,1)
0
>>> cmp(2,1)
1
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
BlackJack

Und wo wir schon beim Sinn von eingebauten Funktionen sind: `hash()` existiert -- das braucht man sich nicht selber schreiben.
theliquidwave
User
Beiträge: 221
Registriert: Sonntag 1. Juni 2008, 09:08

Tatsächliche, danke!
Weißt du zufällig wie die Funktion in der C-API heißt?

Gruß
Grüßle.
BlackJack

@Chrisber: Nein, aber es gibt da ja nicht *die* Funktion -- jeder Datentyp hat seine eigene `__hash__()`-Implementierung.
Antworten