Seite 1 von 1

Können normale Menschen das "==" verstehen?

Verfasst: Donnerstag 26. Februar 2009, 10:42
von Goswin
Meine Python-Bücher (zB Python in a Nutshell) halten die Funktionsweise von == offenbar für so trivial, dass sie sich nicht bemühen, sie näher zu definieren oder zu erklären. Gibt es in Python zwei Klassenobjekte, die beim Vergleich mit == "True" ausgeben?

Code: Alles auswählen

from copy import deepcopy

liste_5 = [31415926535]
liste_6 = [31415926535]
print "liste_5==liste_6 :",liste_5==liste_6 #True

liste_5 = list([31415926535])
liste_6 = list([31415926535])
print "liste_5==liste_6 :", liste_5==liste_6 #True

class Liste(object):
  def __init__(self,xx): self.liste=[xx]
liste_5 = Liste(31415926535)
liste_6 = Liste(31415926535)
liste_7 = deepcopy(liste_5)
print "liste_5==liste_6 :", liste_5==liste_6 #False
print "liste_5==liste_7 :", liste_5==liste_7 #False
Noch gleicher als liste_5, liste_6, liste_7 können zwei Objekte garnicht sein!

Verfasst: Donnerstag 26. Februar 2009, 10:58
von Barabbas
//fehlinformation entfernt ;)

Verfasst: Donnerstag 26. Februar 2009, 10:59
von cofi
Bei eigenen Klassen musst du die Operatoren auch definieren, damit sie funktionieren. Im Klartext heisst das du braucht magic methods ;)

Für Gleichheit wäre das z.B. __eq__:

Code: Alles auswählen

In [2]: class Liste(object):
    def __init__(self, x):
        self.liste = [x]
    def __eq__(self, other_list):
        return self.liste == other_list.liste

In [6]: liste_5 = Liste(31415926535)

In [7]: liste_6 = Liste(31415926535)

In [8]: liste_5 == liste_6
Out[8]: True
Edit: @Barabbas: Nein du verstehst da was falsch. Der Gleichheitsoperator überprüft die Werte der übergebenen Objekte. Was du meinst ist `is', der auf Identität prüft.

Verfasst: Donnerstag 26. Februar 2009, 11:08
von yipyip
Mit

Code: Alles auswählen

liste_5 = Liste(31415926535)
liste_6 = Liste(31415926535)
erzeugst Du doch zwei eigenständige, voneinander unabhängige Objekte.
Willst du dies miteinander vergleichen, so musst Du eine
'__eq__' Methode implementieren:

Code: Alles auswählen

In [6]: class Liste(object):
           def __init__(self, xx): self.liste=[xx]
   ...:     
   ...:     

In [8]: l5 = Liste(1)

In [9]: l6 = Liste(1)

In [10]: id(l5)
Out[10]: 3078872748L

In [11]: id(l6)
Out[11]: 3078871404L

In [12]: l5 == l6
Out[12]: False

In [13]: from copy import deepcopy

In [14]: l7 = deepcopy(l5)

In [15]: id(l7)
Out[15]: 3078869996L

In [16]: l7 == l5
Out[16]: False

In [17]: Liste.__eq__ = lambda self, other: self.liste == other.liste

In [18]: l5 = Liste(1)

In [19]: l6 = Liste(1)

In [20]: l5 == l6
Out[20]: True

In [21]: l7 = deepcopy(l5)

In [22]: id(l7)
Out[22]: 3078871404L

In [23]: id(l5)
Out[23]: 3078870796L

In [24]: l5 == l7
Out[24]: True
:wink:
yipyip

Verfasst: Donnerstag 26. Februar 2009, 11:09
von yipyip
...wieder zu langsam :cry:

Verfasst: Donnerstag 26. Februar 2009, 11:32
von Goswin
In der Tat, jetzt funktioniert es, vielen Dank an cofi & yipyip. Ist bei groe3eren Klassen dann folgendes ausreichend?

Code: Alles auswählen

 def __eq__(self,other): return (self.__dict__ == other.__dict__)
Ich hatte erwartet, dass die Magiemethode __eq__ eine Default-Implementierung hat, was offenbar nicht so ist. Aber wieso gibt es keine Fehlermeldung, wenn ich eine nicht implementierte Methode aufrufe? Oder gilt vielleicht folgendes Default:

Code: Alles auswählen

def __eq__(self,other): return (self is other)

Verfasst: Donnerstag 26. Februar 2009, 11:59
von rayo
Goswin hat geschrieben:In der Tat, jetzt funktioniert es, vielen Dank an cofi & yipyip. Ist bei groe3eren Klassen dann folgendes ausreichend?

Code: Alles auswählen

 def __eq__(self,other): return (self.__dict__ == other.__dict__)
Wuerde ich nicht machen, bei eigenen Klassen gibt es sicher bessere Kriterien wann sie gleich sind. Z.B. der Vor- und Nachname bei der Klasse Person oder andere Members (bei dir self.liste).
Goswin hat geschrieben: Ich hatte erwartet, dass die Magiemethode __eq__ eine Default-Implementierung hat, was offenbar nicht so ist. Aber wieso gibt es keine Fehlermeldung, wenn ich eine nicht implementierte Methode aufrufe? Oder gilt vielleicht folgendes Default:

Code: Alles auswählen

def __eq__(self,other): return (self is other)
In etwa, es wird glaubs einfach die id(obj) verglichen. Python kann ja nicht wissen, was es vergleichen muss bei eigenen Klassen.

Verfasst: Donnerstag 26. Februar 2009, 12:06
von yipyip
Habe grad in meinem 'Python kurz & gut' nachgeschaut:

__eq__ gehört zu den Rich-Comparison-Methoden,
ist es nicht definiert, wird auf __cmp__ zurückgegriffen,
ist auch dies nicht definiert, so werden die Instanzen
anhand ihrer Identität verglichen.

:wink:
yipyip

Verfasst: Freitag 27. Februar 2009, 18:41
von birkenfeld
rayo hat geschrieben:
Goswin hat geschrieben: Ich hatte erwartet, dass die Magiemethode __eq__ eine Default-Implementierung hat, was offenbar nicht so ist. Aber wieso gibt es keine Fehlermeldung, wenn ich eine nicht implementierte Methode aufrufe? Oder gilt vielleicht folgendes Default:

Code: Alles auswählen

def __eq__(self,other): return (self is other)
In etwa, es wird glaubs einfach die id(obj) verglichen.
Was genau äquivalent ist...