Ein paar Fragen über das überladen von operatoren...

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.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

So. Ich versuche mich gerade, in meiner verlängerten Pause in die Methodik hereinzulesen, wie blackbird's Tekisuto funktioniert...

Da dort sehr viel via überladene Operatoren erledigt wird wollte ich mir hier bei einigen Sachen nochmal Klarheit verschaffen.

Fangen wir mal an.
''__new__'' und ''__init__'' hab ich schonmal verstanden.

genauso wie ''__str__''. Das klappt :=)

Jedoch... gibt es dort z.B.

''__repr__''. hier verstehe ich nur Bahnhof. Selbst die Dokumentation hilft mir nicht weiter... Was genau macht __repr__() ?

''__lt__( self, other) ''
''__le__( self, other) ''
''__eq__( self, other) ''
''__ne__( self, other) ''
''__gt__( self, other) ''

sagen mir genauso wenig. Mein Buch sowie die Dokumentation geben mir hier auch keine Auskunft.

Ich kann nur raten, das sie indirekt etwas mit ''__cmp__'' zu tun hat.


Habt ihr dort genauere Informationen - Dokumentationen - Artikel?

Würde mich freuen :)

MfG EnTeQuAk
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

EnTeQuAk hat geschrieben: ''__repr__''. hier verstehe ich nur Bahnhof. Selbst die Dokumentation hilft mir nicht weiter... Was genau macht __repr__() ?
Naja, das zeigt dir genau an was in der Klasse/Instanz ist wenn du ``repr(foo)`` aufrufst.

Code: Alles auswählen

str_ = u"fööbär"
print repr(str_) # u'f\xf6\xf6b\xe4r'
€: Hier zeigt dir repr bei einem Unicode-String an, welche Hexadezimale es in dem gewählt Coding ist.

EnTeQuAk hat geschrieben: ''__lt__( self, other) ''
''__le__( self, other) ''
''__eq__( self, other) ''
''__ne__( self, other) ''
''__gt__( self, other) ''

sagen mir genauso wenig. Mein Buch sowie die Dokumentation geben mir hier auch keine Auskunft.
Dann hast du die falsche. http://docs.python.org/ref/customization.html

x<y = calls x.__lt__(y), x<=y calls x.__le__(y), etc

BTW: __new__ habe ich nicht verstanden. Wie geht das genau?

lg
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

ACH DAAA ;)

Die Seite hab ich mir schon angeschaut gehabt... nur habe ich den Absatz, unter den Sachen, da nur für das ''__ge__'' gesehen :)

Sorry. Ich dachte, die hätten nicht alle ganz so viel miteinander zu tun.

Hmmm... ''__repr__'' schaut doch schon schick aus. so langsam komme ich hinter die Arbeitsweise einiger Lexer :)


MfG EnTeQuAk
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

Btw:

ich hab grad lokal hier Python zum laufen bekommen und '__repr__' ausprobieren können.


folgendes ist herausgekommen:

Code: Alles auswählen

class Test(object):
    def __init__(self):
        self.da = 'da'
    def __repr__(self):
        return ''.join(self.__class__.__name__)

# und testen
da = Test()
repr(da)
print da
So... verwirrt vllt :)

Aber wenn man

Code: Alles auswählen

class Test2(object):
    def __init__(self):
        self.da = 'da'
    def __str__(self):
        return self.da
    def __repr__(self):
        return ''.join(self.__class__.__name__)

# und testen
da = Test()
repr(da)
print da
dann kommt alles heraus, wofür __repr__ da ist :D

So... die anderen schau ich mir dann aúch gleich mal an.


MfG EnTeQuAk
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Darf man fragen, was der Gedanke hinter

Code: Alles auswählen

    def __repr__(self):
        return ''.join(self.__class__.__name__)
ist, insbesondere hinter dem join(...)?

self.__class__.__name__ wird dir afaik immer einen string wiedergeben (den Namen der Klasse, die dir __class__ zurückgibt).
Natürlich kann man den joinen, weil er als String iterabel ist, aber imho sollte für alle Strings gelten

Code: Alles auswählen

s == ''.join(s)
Zu __repr__ möchte ich anmerken, dass es meines Wissens "deprecated" ist.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

EnTeQuAk hat geschrieben:

Code: Alles auswählen

# und testen
da = Test()
repr(da)
print da
Das macht null Sinn ;)

So geht's ehr:

Code: Alles auswählen

# und testen
da = Test()
print repr(da)
:lol:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

EDIT:
das mit dem testen da oben war in einer Python-Shell-Sitzung. daher machte das schon ein klein wenig sinn, da mir das dort ausgegeben wurde -- sorry hab ich vergessen zu erwähnen


Wie an den Klassennamen zu merken :D es war nur ein Test. Daher habe ich mir über Sinn und Unsinn mal keine Gedanken gemacht.

Zu __repr__ möchte ich anmerken, dass es meines Wissens "deprecated" ist.
hmm... warum?
Natürlich kann man den joinen, weil er als String iterabel ist, aber imho sollte für alle Strings gelten

Code: Alles auswählen

s == ''.join(s)
bin ich auf dem falschen Dampfer oder macht das nur für mich keinen Sinn, da da so oder so 'True' rauskommt?

Oder was war bei dir der Hintergedanke? :D

MfG EnTeQuAk
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

[warum ist repr deprecated]
Nagele mich nicht drauf fest, ich erinnere mich, da was gelesen zu haben, was darauf rauslief, dass es kaum einer richtig benutzt (soll heissen: repr gibt etwas aus, was nicht nur hübsch aussieht, sondern auch ein legales python-statement ist), und man es deshalb eigentlich eh nicht benutzen kann. Kann ich eigentlich ganz gut nachvollziehen, und es hindert ja niemanden daran, für sich ein "representable"-Protokoll zu erfinden.
bin ich auf dem falschen Dampfer oder macht das nur für mich keinen Sinn, da da so oder so 'True' rauskommt?
Doch, doch, du hast recht, es kommt immer True raus: das ganze ist eine Tautologie, deshalb sagte ich ja "es gilt für alle strings". Eigentlich wollte ich damit zeigen, dass dein Statement nicht falsch (im Sinne der Funktionalität), sondern nur unnötig kompliziert ist, weil ich annahm, dass sei Absicht.
EnTeQuAk
User
Beiträge: 986
Registriert: Freitag 21. Juli 2006, 15:03
Wohnort: Berlin
Kontaktdaten:

ACHSOOOOO :D


Dann haben wir uns ja im Enddefekt verstanden :D


Und ich bin wieder einen Schritt weiter in Python gekommen... Ich mag es :D


MfG EnTeQuAk
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

keppla hat geschrieben: Zu __repr__ möchte ich anmerken, dass es meines Wissens "deprecated" ist.
Ist es nicht.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
BlackJack

keppla hat geschrieben:[warum ist repr deprecated]
Nagele mich nicht drauf fest, ich erinnere mich, da was gelesen zu haben, was darauf rauslief, dass es kaum einer richtig benutzt (soll heissen: repr gibt etwas aus, was nicht nur hübsch aussieht, sondern auch ein legales python-statement ist), und man es deshalb eigentlich eh nicht benutzen kann. Kann ich eigentlich ganz gut nachvollziehen, und es hindert ja niemanden daran, für sich ein "representable"-Protokoll zu erfinden.
`repr` muss nicht "legales Python" zurückgeben. Wenn das einfach möglich ist, wäre es schön, aber es muss nicht. Falls es nicht möglich ist, wird empfohlen etwas aussagekräftiges zurückzugeben, das in '<…>' eingeschlossen ist. Und das habe ich bisher auch so ziemlich überall so implementiert gesehen.

Ich wüsste auch nicht wie man ein Python-Programm debuggen sollte, ohne mit `repr()` nachschauen zu können, an was bestimmte Namen wirklich gebunden sind.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

`repr` muss nicht "legales Python" zurückgeben
ok, ich sollte mich etwas näher an das RFC, was "muss", "soll", "kann" definiert halten. ;)

Ich hab nochmal etwas gesucht, und da, wo ich dachte, ich hätte es gelesen, nichts solches gefunden, und muss mich dementsprechend für das verbreiten von falschinformationen entschuldigen: ich hatte da was falsch in Erinnerung, birkenfeld hat recht.

Code: Alles auswählen

Ich wüsste auch nicht wie man ein Python-Programm debuggen sollte, ohne mit `repr()` nachschauen zu können, an was bestimmte Namen wirklich gebunden sind.
dazu braucht man nicht unbedingt die Unterscheidung str und repr, z.B. Java kommt auch mit nur .toString aus. id() ist ausserdem eindeutiger ;)
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

keppla hat geschrieben: dazu braucht man nicht unbedingt die Unterscheidung str und repr, z.B. Java kommt auch mit nur .toString aus.
Dann unterscheide doch mal anhand von str() "1" und 1.
Oder "1.0" und 1.0. Oder...

Um da den Durchblick zu behalten, musst du zumindest den Typ noch mit dazu ausgeben. Genau das macht aber repr().
id() ist ausserdem eindeutiger ;)
id() bringt dir garnix.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

keppla hat geschrieben: dazu braucht man nicht unbedingt die Unterscheidung str und repr, z.B. Java kommt auch mit nur .toString aus. id() ist ausserdem eindeutiger ;)
In wiefern eindeutiger? Mit einer Zahl kann ich persönlich ohne andere Informationen wenig anfangen. Und das was repr ausgibt oder ausgeben sollte ist ja ein wenig mehr als nur eine Zahl (Oder "Adresse" im Default mode).

Ich finde es z.B. nicht schlecht das ich mit __str__ mir nur das anzeigen lassen kann was wichtig ist nach ausenhin, aber mit __repr__ (zusätzlich) ein wenig mehr Daten über Interna :) Das hilf schon beim Debuggen, wenn man weiß womit man es zu tun hat. Ich überlade __repr__ auch so ähnlich wie im Tekisuto-Code von BlackBird.

Also kurz: Für mich gehört es einfach dazu, dass wenn ich repr(foo) nutze, mir der Name der Klasse zurückgegeben wird, damit ich weiß an was der Name `foo` gebunden ist (Ist im Default ja schon so + "Addresse", etc).
Oft genügen mir diese Information nicht und will ein par Infos (Ohne nötigen Schreibkram) über das interne mehr haben und überlade __repr__ da entsprechend. Wichtig ist aber, dass in der Überladung IMHO immer zusätlich sowas ``self.__class__.__name__`` zurückgegeben werden muss, damit man auch sieht an was ``foo`` gebunden ist.

BTW: Daher finde ich id() auch unpassend, da ich mit einer ID immer eine eindeutige (Kollisionsfreie) Zahl, assoziiere.

lg
EDIT:
BTW: Außerdem ist id() schon von Python als Keyword belegt ;) Es sein den du meintest das du die Benutzung von id() eindeutiger findest :shock:
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

sape hat geschrieben: BTW: Außerdem ist id() schon von Python als Keyword belegt ;) Es sein den du meintest das du die Benutzung von id() eindeutiger findest :shock:
Klar meint er das. Aber id() ist kein Keyword, sondern eine Funktion in den Builtins.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Ups, stimmt ja.

lg
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

id() bringt dir garnix
Wenn ich wissen will, an _welches_ Objekt ein name gebunden ist, bringt mir das mehr als eine (möglicherweise gleich aussehende) Ausgabe eines __repr__. Das meinte ich auch mit eindeutiger:

Code: Alles auswählen

d1 = datetime(2007,1,31)
d2 = datetime(2007,1,31)

assert repr(d1) == repr(d2)
assert d1 is not d2
 
Dann unterscheide doch mal anhand von str() "1" und 1.
Oder "1.0" und 1.0. Oder...
Um da den Durchblick zu behalten, musst du zumindest den Typ noch mit dazu ausgeben. Genau das macht aber repr().
Da gucke ich lieber debugger nach, da habe ich dann auch einen ganzen Haufen andere infos. Ich bin kein so großer Freund von Printlining.
BlackJack

keppla hat geschrieben:
id() bringt dir garnix
Wenn ich wissen will, an _welches_ Objekt ein name gebunden ist, bringt mir das mehr als eine (möglicherweise gleich aussehende) Ausgabe eines __repr__. Das meinte ich auch mit eindeutiger:

Code: Alles auswählen

d1 = datetime(2007,1,31)
d2 = datetime(2007,1,31)

assert repr(d1) == repr(d2)
assert d1 is not d2
 
Tests auf Objektidentität ist nur in wenigen Fällen wirklich sinnvoll/interessant. Bei `datetime` fällt mir da überhaupt kein Grund ein. Werte und Typen sind eher interessant. Wobei ein nicht unbeträchtlicher Teil von Klassen `__repr()__` gar nicht überschreibt, man also Typ und Identität auf einmal bekommt.
Benutzeravatar
keppla
User
Beiträge: 483
Registriert: Montag 31. Oktober 2005, 00:12

Tests auf Objektidentität ist nur in wenigen Fällen wirklich sinnvoll/interessant.


Ich hatte das so aus der Beschreibung rausgelesen (welches objekt an einen namen gebunden ist).
Bei `datetime` fällt mir da überhaupt kein Grund ein.
Das war auch eher des Beispiels wegen, ich hab halt ne vorhandene Klasse gewählt.
Antworten