Seite 1 von 1
Funktionsdefinition innerhalb einer Schleife
Verfasst: Sonntag 12. Juli 2009, 19:20
von Knüppeltag
Hi,
habe bis jetzt immer nur in C programmiert und muss mich jetzt erstmal an python gewöhnen. Bis jetzt gefällt es mir aber super.
Allerdings hätte ich jetzt aber mal ein Frage zu Funktionsdefinitionen. In diesem Codebeispiel gibt es eine Funktionsdefinition in einer Schleife
Code: Alles auswählen
while True:
# ... ein bischen code
def draw_something(color, position):
# ... inhalt der draw funktion
draw_something(white, pos1)
draw_something(green, pos2)
draw_something(yellow, pos3)
# ... weiterer code
Was passiert hier?
Wird jetzt in jedem Schleifendurchgang die Funktion 'draw_something' neu definiert werden und wenn ja, wäre das nicht ziemlich langsam?
Danke schon mal
Re: Funktionsdefinition innerhalb einer Schleife
Verfasst: Sonntag 12. Juli 2009, 19:23
von numerix
Knüppeltag hat geschrieben:
Was passiert hier?
Wird jetzt in jedem Schleifendurchgang die Funktion 'draw_something' neu definiert
Ja, so ist es. Allem Anschein nach ist das von jemandem ziemlich schlecht programmiert worden. Die Funktionsdefinition gehört nicht in die Schleife.
Verfasst: Sonntag 12. Juli 2009, 19:33
von Knüppeltag
Das ist aus dem Buch 'Beginning Game Development with Python and Pygame'. Dort wird das laufend so gemacht. Manchmal sind es sogar mehr als 2 Funktionsdefinitionen in einer Schleife.
Das spricht dann ja nicht gerade für den Autor.
Verfasst: Sonntag 12. Juli 2009, 20:03
von Leonidas
Naja, ohne Profiling müsste man es nicht unbedingt verurteilen. Vielleicht ist es ja eine Closure oder der Programmierer stammt aus einer Sprache in der anonyme Funktionen populärer sind als in Python.
Verfasst: Sonntag 12. Juli 2009, 21:05
von BlackJack
@Knüppeltag: Man kann zu dem Buch Quelltexte herunterladen:
http://www.apress.com/book/downloadfile/3765
Da wird das soweit ich das sehen kann nur *einmal* in 12 Kapiteln gemacht. In Kapitel 8 bei `rotation3d.py`.
Kann es sein, dass im Buchtext der Quelltext unterbrochen von Absätzen nicht linear gezeigt wird!?
Ansonsten sehen die Quelltexte, zumindest so vom kurz drüberschauen, auch nicht besonders "schlimm" aus.
Verfasst: Sonntag 12. Juli 2009, 21:32
von Knüppeltag
Hehe, das mt dem "laufend" war wohl etwas übertrieben

. Es kommt tatsächlich nur in rotation3d.py vor.
Ansonsten sehen die Quelltexte, zumindest so vom kurz drüberschauen, auch nicht besonders "schlimm" aus.
Ja, die Quelltexte sehen nicht schlimm aus. Eigentlich wollte ich nur wissen, ob das ein anerkannter Python coding style oder so ähnlich ist. Also, dass man Funktionen einfach so in einer Schleife definiert.
Aber da das anscheinend wirklich die Performance verschlechtert, sollte man das wohl lieber nicht auf diese Weise machen.
Für kleine Testprogramme wie im Buch, ist es aber dann wohl legitim. Kann man das so sagen?
Verfasst: Sonntag 12. Juli 2009, 21:45
von cofi
Knüppeltag hat geschrieben:Für kleine Testprogramme wie im Buch, ist es aber dann wohl legitim. Kann man das so sagen?
Legitim ist alles was der Interpreter frisst und die Entwickler sich und anderen zumuten - nicht zuletzt den Anwendern im Hinblick auf Performance.
Obiges gilt fuer Produktionscode, was du dagegen in deinem Sandkasten aka
interaktive Interpretersession machst, ist ganz egal
Wenn dich das Thema Coding Style interessiert, solltest du [wiki]PEP 8 (Übersetzung)[/wiki] oder
das Original anschauen.
Dort werden solche Details zwar nicht angesprochen, dafuer aber der Rest. Ob du den Stil des Buches anwendest bleibt dir und deinem (gesunden) Menschenverstand ueberlassen (PEP 8 ist aber drigend empfohlen

)
Wenn du dazu eine Hilfe willst:
Verfasst: Sonntag 12. Juli 2009, 22:07
von Darii
Knüppeltag hat geschrieben:Aber da das anscheinend wirklich die Performance verschlechtert, sollte man das wohl lieber nicht auf diese Weise machen.
Ich würde das nicht überbewerten, Python ist ja sowieso schon vergleichsweise langsam. Wie heißt es so schön: „Premature optimization is the root of all evil.“
Verfasst: Sonntag 12. Juli 2009, 22:13
von BlackJack
@Knüppeltag: Also ich würde das als kleineren Schönheitsfehler ansehen. Das ist so ähnlich wie das Ausrechnen eines Wertes in einer Schleife, wo sich der Wert aber garantiert nie ändert. Also etwas das man vor die Schleife ziehen sollte.
"Erschwerend" kommt hier dazu, dass so eine Funtkionsdefinition eher die Frage aufwirft *warum* das in der Schleife gemacht wird, und der Leser ein wenig Zeit darauf ver(sch)wenden muss, ob das einen Sinn hat, oder nicht. Wenn ich so etwas in einer Schleife sehe, denke ich zuerst an ein Closure.
Verfasst: Sonntag 12. Juli 2009, 22:21
von hendrikS
Darii hat geschrieben:Ich würde das nicht überbewerten, Python ist ja sowieso schon vergleichsweise langsam. Wie heißt es so schön: „Premature optimization is the root of all evil.“
Funktionsdefinition in einer Schleife ist einfach suboptimal. Da gibt es nichts zu beschwichtigen.
Verfasst: Sonntag 12. Juli 2009, 22:47
von BlackJack
*Sinnlose* Funktionsdefinitionen!
Verfasst: Montag 13. Juli 2009, 21:48
von birkenfeld
So furchtbar, wie manche das hier darstellen, sind Funktionsdefinitionen in einer Schleife nicht. Da die Funktion nur einmal kompiliert wird, fällt pro Durchlauf nur ein Laden des konstanten Codeobjekts und erstellen eines Funktionsobjekts daraus an.
Dass das bei komplizierten Funktionen bald vernachlässigbar wird, sieht man z.B. hieran:
Code: Alles auswählen
import math, time
def a():
for i in xrange(1, 1000000):
def foo(x):
math.log(x) + 1 - math.exp(1 - x**2)
foo(i)
def b():
def foo(x):
math.log(x) + 1 - math.exp(1 - x**2)
for i in xrange(1, 1000000):
foo(i)
def c():
for x in xrange(1, 1000000):
math.log(x) + 1 - math.exp(1 - x**2)
x1 = time.time()
a()
x2 = time.time()
b()
x3 = time.time()
c()
x4 = time.time()
print 'innerhalb:', x2-x1
print 'ausserhalb:', x3-x2
print 'ohne fkt:', x4-x3
Bei mir gibt das aus:
Code: Alles auswählen
innerhalb: 6.42580318451
ausserhalb: 6.02840685844
ohne fkt: 5.32613611221
Die zusätzliche Funktionsdefinition macht also unter 10% zusätzlicher Laufzeit aus, und das, obwohl in der Funktion "nur" ein paar einfache mathematische Operationen ausgeführt werden.
Der Funktionsaufruf "kostet" sogar mehr als die Funktionsdefinition, wie man am letzten Beispiel sieht!
Verfasst: Montag 13. Juli 2009, 22:28
von hendrikS
Kann ich bestätigen. Hab auch ein bißchen rumexperimentiert. Performanceeinbußen sind relativ gering. In meinem Test etwa 4%. Sympatisch ist mir das trotzdem nicht.
Verfasst: Montag 13. Juli 2009, 22:55
von birkenfeld
Klar. In den meisten Fällen ist es denke ich einfach ein Versehen.
Verfasst: Dienstag 14. Juli 2009, 08:12
von Darii
In dem speziellen Fall wäre die Alternative ein Funktionsaufruf mit 7 Parametern von denen sich die 4 zusätzlichen nicht unterscheiden. Wenn man sich so viel Sorgen um die Geschwindigkeit macht, hätte man imo nicht Python nehmen sollen (ich will damit nicht sagen, dass man deswegen ohne Sinn und Verstand vorgehen sollte).
Verfasst: Dienstag 14. Juli 2009, 08:54
von birkenfeld
Darii hat geschrieben:In dem speziellen Fall wäre die Alternative ein Funktionsaufruf mit 7 Parametern von denen sich die 4 zusätzlichen nicht unterscheiden.
Dazu braucht man die Funktion aber nicht in der Schleife definieren.
Verfasst: Dienstag 14. Juli 2009, 21:07
von Darii
birkenfeld hat geschrieben:Darii hat geschrieben:In dem speziellen Fall wäre die Alternative ein Funktionsaufruf mit 7 Parametern von denen sich die 4 zusätzlichen nicht unterscheiden.
Dazu braucht man die Funktion aber nicht in der Schleife definieren.
? Sage ich doch. Wenn man die Funktion nicht in der Schleife definieren würde, bräuchte man alternativ 7 Parametern von denen sich die 4 zusätzlichen wiederholen.
Code: Alles auswählen
draw_axis(red, x_axis, x_surface, screen, viewing_distance, rotation_matrix, camera_position)
draw_axis(green, y_axis, y_surface, screen, viewing_distance, rotation_matrix, camera_position)
draw_axis(blue, z_axis, z_surface, screen, viewing_distance, rotation_matrix, camera_position)
Edit: ok screen könnte man sich noch schenken, das wars aber schon...
Verfasst: Dienstag 14. Juli 2009, 22:12
von birkenfeld
Nein, das bräuchte man eben nicht. Diese Namen kannst du in der Funktion verwenden, und sie werden automatisch im umgebenden Namensraum gefunden.
Verfasst: Mittwoch 15. Juli 2009, 07:45
von Leonidas
Closures ftw.
Verfasst: Mittwoch 15. Juli 2009, 09:01
von Darii
birkenfeld hat geschrieben:Nein, das bräuchte man eben nicht. Diese Namen kannst du in der Funktion verwenden, und sie werden automatisch im umgebenden Namensraum gefunden.
Ach mist stimmt, ich hatte total übersehen dass Schleifen ja gar keinen neuen Namenraum haben.