Principle of Biggest Surprise

Gute Links und Tutorials könnt ihr hier posten.
Antworten
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

Ich bitte um Feedback zu meinem Artikel. Danke im vorraus.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
BlackJack

Also `copy.copy()` ist IMHO keine "Überraschung". Oder zumindest eine bei der es nicht überraschend ist, dass es Leute überraschen *muss*, *egal* wie man es konkret implementiert. Einige sind überrascht, dass bei einer Liste nur eine flache Kopie gemacht wird, andere, dass die Kopie bei Klassen *noch* flacher ist. :-)

Bei `__del__()` stimmt die Behauptung mit der fehlenden Warnung nicht. Die Dokumentation beschreibt das durchaus und hat auch einen extra hervorgehobenen Textkasten. Das grosse Problem hier sind IMHO so tolle Bücher wie das OpenBook von Galileo, die nicht nur die Warnung nicht wiedergeben, sondern auch noch so tun, als sei `__del__()` eine nützliche Methode für Python-Objekte. Das ist sie nun einmal nicht.

Bücher und Tutorials müssten `__del__()` einfach nicht erwähnen, oder halt deutlich mit der Warnung versehen, welche Randbedingungen hier gelten.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

BlackJack hat geschrieben:Also `copy.copy()` ist IMHO keine "Überraschung". Oder zumindest eine bei der es nicht überraschend ist, dass es Leute überraschen *muss*, *egal* wie man es konkret implementiert. Einige sind überrascht, dass bei einer Liste nur eine flache Kopie gemacht wird, andere, dass die Kopie bei Klassen *noch* flacher ist. :-)
Wenn copy.copy das Original zurueckgibt is das ne Ueberraschung. Da is eine Exception besser.
BlackJack hat geschrieben:Bei `__del__()` stimmt die Behauptung mit der fehlenden Warnung nicht. Die Dokumentation beschreibt das durchaus und hat auch einen extra hervorgehobenen Textkasten. Das grosse Problem hier sind IMHO so tolle Bücher wie das OpenBook von Galileo, die nicht nur die Warnung nicht wiedergeben, sondern auch noch so tun, als sei `__del__()` eine nützliche Methode für Python-Objekte. Das ist sie nun einmal nicht.
Ich meinte eine Warnung zur Laufzeit das man einen unloesbaren Referenzkreis hat.
BlackJack hat geschrieben:Bücher und Tutorials müssten `__del__()` einfach nicht erwähnen, oder halt deutlich mit der Warnung versehen, welche Randbedingungen hier gelten.
Also einfach ned verwenden? Ist finde ich auch keine Loesung.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Zu __del__: Java hat das gleiche Problem mit der Methode finalize(), von der auch abgeraten wird. Die Implementierung von __del__ hat ganz gewaltige Probleme mit dem GC, und anscheinend sind die nicht einfach zu lösen. Siehe hier: http://de.wikipedia.org/wiki/Garbage_Co ... alisierung

Die Geschichte mit str() und anderen "magic methods" ist wirklich suboptimal, dürfte aber der einzige Platz sein, an welchen explizit in der Klasse nachgeschaut wird (und Class.__str__(inst) aufgerufen wird statt inst.__str__()).
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

str1442 hat geschrieben:Die Geschichte mit str() und anderen "magic methods" ist wirklich suboptimal, dürfte aber der einzige Platz sein, an welchen explizit in der Klasse nachgeschaut wird (und Class.__str__(inst) aufgerufen wird statt inst.__str__()).
Eigentlich wird ja typestruct->tp_str aufgerufen, sonst waer das ganze ja sinnlos. Gerade *das* es der einzige Platz ist, macht es so schlimm. Waer alles lookup in der Klasse, was solls.
Zuletzt geändert von name am Sonntag 28. Juni 2009, 10:34, insgesamt 1-mal geändert.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Das mit der Auflösung der Magic Methods würde mich jetzt nicht so stören wenn man dass über Metaklassen beeinflussen könnte.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

DasIch hat geschrieben:Das mit der Auflösung der Magic Methods würde mich jetzt nicht so stören wenn man dass über Metaklassen beeinflussen könnte.
Was ja nicht geht, weil der struct lookup __getattribute__ umgeht.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

str1442 hat geschrieben:Zu __del__: Java hat das gleiche Problem mit der Methode finalize(), von der auch abgeraten wird. Die Implementierung von __del__ hat ganz gewaltige Probleme mit dem GC, und anscheinend sind die nicht einfach zu lösen. Siehe hier: http://de.wikipedia.org/wiki/Garbage_Co ... alisierung
Mein Vorschlag waere eine Magic-Method die wenn bei einem Objekt im Cycle vorhanden die Objekte in der Reihenfolge in der sie deallokiert werden sollen zurueckgibt, nur das is noch nicht ganz durchgedacht.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
BlackJack

@name: Was meinst Du wie viele Leute von einer Laufzeitwarnung über unauflösbare Kreise überrascht wären und sich beschweren würden, dass sie die Warnung nicht haben wollen. :-)

Magic Methods werden "eigentlich" in der Klasse nachgeschlagen. Das ist die Ebene auf der Python's Semantik definiert ist. ``typestruct->tp_str`` ist kein Python und findet sich so sicher auch nicht in Jython oder IronPython wieder. Das ist ein Implementierungsdetail von CPython.

`__del__()` in Python-Klassen nicht zu verwenden ist *die* Lösung. Wird von Java-Programmierern mit `finalize()` ja auch so gemacht. Die Methode ist ein Entwurfsfehler, der in beiden Sprachen mal gemacht wurde. Andererseits braucht man sie in Typen, die nicht in Python implementiert wurden, um Ressourcen wieder freigeben zu können, die nicht im Einflussbereich des Python-Interpretierers liegen.

Ich denke mal sollte `__del__()` einfach nicht implementieren, dann hat man auch keine Probleme mit Kreisbeziehungen. Deine neue "magic method", die das Problem beheben soll, geht ja noch mehr in Richtung manuelle Ressourcenverwaltung als man das mit `__del__()` sowieso schon tut, obwohl man damit ja meistens versuchen will etwas "automagisch" wieder freizugeben. Ich denke da ist es einfacher eine Methode zum Aufräumen explizit aufzurufen, oder mit ``with`` zu arbeiten.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

BlackJack hat geschrieben:Magic Methods werden "eigentlich" in der Klasse nachgeschlagen. Das ist die Ebene auf der Python's Semantik definiert ist. ``typestruct->tp_str`` ist kein Python und findet sich so sicher auch nicht in Jython oder IronPython wieder. Das ist ein Implementierungsdetail von CPython.
Wenn dem so ist implementiert CPython Python falsch. Weil ja __getattribute__ (der metacls) etc ignoriert werden. Also wirds ned direkt in der Klasse nachgeschlagen, hoechstens direkt im Klassen-Dict. (kleiner, aber wichtiger Unterschied)
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

BlackJack hat geschrieben:`__del__()` in Python-Klassen nicht zu verwenden ist *die* Lösung.
Ich habe Objekte (SeqAlg) die an einen offenen File-Pointer gebunden sein müssen. Außerdem habe ich einen Container, die viele dieser SeqAlg Instanzen vorhält und deshalb Referenzen zu ihnen hat. Außerdem möchte ich einer SeqAlg Instanzen erlauben, sich selbst zu manipulieren und daraus neue SeqAlg Instanzen (mit neuen File-Pointern) zu erschaffen, die wiederum in den Container eingepflegt werden müssen. Dafür brauch ich die Referenz zum Container im SeqAlg Objekt. SeqAlg braucht __del__() für das fp.close(). Wie mache ich sinnvoll das ohne __del__ oder ohne Kreisabhängigkeiten?
BlackJack

@name: Den kleinen aber feinen Unterschied verstehe ich nicht. Ist wohl zu fein.

@Defnull: Wenn man sich auf `__del__()` als deterministischen Destruktor verlässt, ist IMHO das Programm fehlerhaft. Es ist von der Sprache ja nicht einmal garantiert, dass `__del__()` überhaupt jemals aufgerufen wird. Und Dateideskriptoren können ganz real schneller knapp werden, als die Speicherbereinigung mit dem Abräumen von Objekten hinterherkommt. Habe ich bei Java schon erlebt.

Wobei ich jetzt nicht sehe, warum der Container unbedingt eine `__del__()`-Methode braucht!? Wenn der keine hat, kann er ja problemlos abgeräumt werden und schon ist die Kreisbeziehung Container<->SeqAlg gelöst.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

BlackJack hat geschrieben:@name: Den kleinen aber feinen Unterschied verstehe ich nicht. Ist wohl zu fein.
Wenn die metaclass __getattribute__ ueberschreibt ist dict-lookup ned unbedingt das selbe wie lookup in der Klasse.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
lunar

name hat geschrieben:
DasIch hat geschrieben:Das mit der Auflösung der Magic Methods würde mich jetzt nicht so stören wenn man dass über Metaklassen beeinflussen könnte.
Was ja nicht geht, weil der struct lookup __getattribute__ umgeht.
Dafür ist der direkte Zugriff über die C-Datenstruktur wahrscheinlich um Welten schneller als ein teurer Aufruf einer Python-Methode. Die Entscheidung, den Zugriff direkt zu implementieren, trägt einer Realität Rechnung, in der Szenarien, in denen diese Methoden aufgerufen werden, weitaus häufiger sind als solche, in denen diese Methoden über __getattribute__ manipuliert werden müssten, und ist daher durchaus nachvollziehbar und meiner Meinung nach auch sinnvoll.
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

Ich denke ja immernoch persönlich, dass _del_ seine Einsatzberechtigung in seiner momentanen Form hat.

Ich würde gerne mal nachschauen, ob die Entwickler von Python es irgendwie einsetzen. Ich würde wetten! Manchmal sollen eben Sachen passieren, direkt nachdem der GC das Objekt weggeräumt hat. Nicht bei der Dereferenzierung, sondern wirklich beim wegräumen vom Garbage Collecter. Nur als normaler Programmierer, der keine Sprache entwickeln will, brauch man diesen Fall selten bis nie.

Man könnte noch eine Dereferenzierungsoperation einbauen. Aber was ist, wenn ein Objekt 2 Referenzen hat? Wird der dann 2mal aufgerufen?

Code: Alles auswählen

>>> class A(object):
...     pass
...
>>> a = A()
>>> b = a
>>> a is b
True
>>> del a
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
<__main__.A object at 0x00AAD7F0>
>>> del b
>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
Garbage Collecter sind halt für solche Fälle nicht so gut. Aber es gibt genug andere Wege, das zu umgehen. Deswegen is's für mich kein Problem.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

lunar hat geschrieben:
name hat geschrieben:
DasIch hat geschrieben:Das mit der Auflösung der Magic Methods würde mich jetzt nicht so stören wenn man dass über Metaklassen beeinflussen könnte.
Was ja nicht geht, weil der struct lookup __getattribute__ umgeht.
Dafür ist der direkte Zugriff über die C-Datenstruktur wahrscheinlich um Welten schneller als ein teurer Aufruf einer Python-Methode. Die Entscheidung, den Zugriff direkt zu implementieren, trägt einer Realität Rechnung, in der Szenarien, in denen diese Methoden aufgerufen werden, weitaus häufiger sind als solche, in denen diese Methoden über __getattribute__ manipuliert werden müssten, und ist daher durchaus nachvollziehbar und meiner Meinung nach auch sinnvoll.
Es ging darum zu zeigen, dass es eben nicht in der Klasse, sondern wo anders, gelookupt wird, anders als BlackJack behauptet hat.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
lunar

Mir ging es um den konkreten Kritikpunkt in deinem Artikel. Deswegen habe ich auch einen Satz zitiert, der vor der Diskussion mit BlackJack über den Attributzugriff fiel ;)
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

lunar hat geschrieben:Mir ging es um den konkreten Kritikpunkt in deinem Artikel. Deswegen habe ich auch einen Satz zitiert, der vor der Diskussion mit BlackJack über den Attributzugriff fiel ;)
Trotzdem, wenn in der Klasse, dann alles. Wenn nicht in der Klasse, dann nichts. Ich bleib dabei.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
lunar

Ich hätte mir denken können, dass du dabei bleibst ... ich persönlich halte es für eine unschöne, aber eben notwendige Entwurfsentscheidung zugunsten einer höheren Ausführungsgeschwindigkeit.
Benutzeravatar
name
User
Beiträge: 254
Registriert: Dienstag 5. September 2006, 16:35
Wohnort: Wien
Kontaktdaten:

lunar hat geschrieben:Ich hätte mir denken können, dass du dabei bleibst ... ich persönlich halte es für eine unschöne, aber eben notwendige Entwurfsentscheidung zugunsten einer höheren Ausführungsgeschwindigkeit.
Dann doch alles in der klasse, da spart man sich dann noch viele hashtables.
Ohloh | Mein Blog | Jabber: segfaulthunter@swissjabber.eu | asynchia – asynchrone Netzwerkbibliothek

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.
Antworten