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

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
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

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!
Barabbas
User
Beiträge: 349
Registriert: Dienstag 4. März 2008, 14:47

//fehlinformation entfernt ;)
Zuletzt geändert von Barabbas am Donnerstag 26. Februar 2009, 11:04, insgesamt 4-mal geändert.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

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
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

...wieder zu langsam :cry:
Benutzeravatar
Goswin
User
Beiträge: 363
Registriert: Freitag 8. Dezember 2006, 11:47
Wohnort: Ulm-Böfingen
Kontaktdaten:

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)
rayo
User
Beiträge: 773
Registriert: Mittwoch 5. November 2003, 18:06
Wohnort: Schweiz
Kontaktdaten:

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.
yipyip
User
Beiträge: 418
Registriert: Samstag 12. Juli 2008, 01:18

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
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

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...
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Antworten