Absurd: Rückgabe-Wert(e) in Python

  • Hallo zusammen, speziell die Python-Spezialisten hier.

    Python bietet offensichtlich die Möglichkeit, dass eine Funktion mehrere Werte zurückliefern kann.
    Da ich aus der C-Welt komme, finde ich das ganz schön schräg.
    In meiner Welt hat eine Funktion entweder keinen oder aber einen Rückgabewert, z.B. 0 bzw. Fehlercode oder Character-String bzw. NULL. Alles andere wird über die Parameter/Argumente behandelt. Ich wüsste auch gar nicht, wie ich mehrere Rückgabe-Werte auswerten/zuweisen sollte.

    Kann mir da jemand von Euch Script-Cracks mit einem kurzen Beispiel ( sonst bitte Code bzw. Spoiler verwenden ) mal auf die Sprünge helfen?

    Danke schon mal,
    -ds-

  • Wie schön dir auch mal auf die Sprünge helfen zu können, auch wenn ich noch nicht soo viel Plan von Python hab :D

    Hoffentlich ist das auch was du willst:

    Ausgabe:

    Code
    root@raspberrypi:/tmp# python test
    a: 123 , b: 456 , c: 789
    a: 987 b: 654 c: 321
    a: bl, b: ub, c: ber
    root@raspberrypi:/tmp#
  • Nett wenn Du nicht nur einen RC sondern auch noch einen weitere FehlerCode returnen willst.

    Ausgabe des Scripts:

    Code
    ('one', 'two') <type 'tuple'>
    one - two
    <type 'str'> <type 'str'>
    one - two
  • Hallöle,

    danke erstmal.
    Hi meigrafd, knapp am Bullseye vorbei ;) ...

    Ich dachte da mehr an so was:

    Code
    # Hauptprogramm
     		f, u = geom(3, 7)
    		print "Fläche:", f
    		print "Umfang:", u
    		x = geom(2,5)
    		print "Fläche:", x[0]
    		print "Umfang:", x[1]


    mit der Funktion geom():

    Code
    # Funktionsdefinition
     		def geom(breite, laenge):
     		  flaeche = breite * laenge
    		  umfang = 2 * (breite * laenge)
    		  return flaeche, umfang

    Das mag auf den ersten Blick sinnvoll sein (siehe auch Antwort von framp. BTW das war Dein 1000ster Post :thumbs1:).
    Auch beim Link von Bjoern ( siehe obiges Beispiel ) scheint das zunächst ein sinnvolles Feature zu sein.
    Ich für meinen Teil finde es trotzdem abartig und verwirrend. Die geom() Funktion, ist die jetzt dazu da, den Umfang oder die Fläache zu beechnen?
    Das ist doch in C:

    Code
    float rect_surface_calc( float l, float h ); 
    float rect_coverage_calc( float l, float h );
    // Gibt die Fläche bzw. den Umfang eines Rechtecks zurück oder -1 im Fehlerfall


    m.E. wesentlich übersichtlicher, oder nicht?

    Nun gut, man kann - muss das abernicht verwenden. Das ist meine rettung ;) ...

    cu,
    -ds-

  • Naja rect_surface_calc wird denk ich auch nur eine definierte Anweisung sein :huh: Was anderes machst du dann ja in Python auch nicht, ob die Anweisung nun rect_surface_calc oder geom heißt... :D (http://support7.qnx.com/download/download/12083/cs_demo1.c)

    Wobei ich die geom nicht so:

    Code
    def geom(breite, laenge):
    	flaeche = breite * laenge
    	umfang = 2 * (breite * laenge)
    	return flaeche, umfang

    Sondern so machen würde:

    Code
    def geom(breite, laenge):
    	flaeche = breite * laenge
    	umfang = 2 * flaeche
    	return flaeche, umfang

    Aber ändern tut das wenig


  • ...BTW das war Dein 1000ster Post :thumbs1:)...


    Oha, das haette ich beinahe verpasst. Danke fuer den Hinweis.

    Zitat


    ...Ich für meinen Teil finde es trotzdem abartig und verwirrend. Die geom() Funktion, ist die jetzt dazu da, den Umfang oder die Fläache zu beechnen?...


    Wie Du schon geschrieben hast ist das ein kann, Kein Muss. Es kommt einfach auf das verwendete Programmiermodell an. In C liefert eine Funktion oder Methode immer nur ein Ergebnis zurueck. Wenn man mehrere liefern will muss man das ueber passed by reference Parameter als Argumente machen. Das geht natuerlich auch in Python. Oder man returned in C eine Referenz auf Objekte/Strukturen zurueck. Allerdings ist dann wichtig, dass die Ownership des erzeugten Objekts an den Caller uebergeht und er das kontrolliert mit free. Ansonsten hagelt es Memoryleaks :lol:. In Python hast Du einen GarbageCollector der das fuer Dich erledigt.

  • Hi framp und alle anderen,

    nun - gerade die Garbage-Geschichte ( das Betriebssysten gibt ohnehin bei Prozess-Ende alle belegten Resourcen frei ) verführt imho zu einem unsauberen Programmierstil ( man muss sich praktisch nicht mehr um Speicerblöcke kümmern - allerdings bestätigen mal wieder Ausnahmen die Regel - siehe -> hier <- in Teil 1).
    Nun, glücklicherweise ist es ein Kann, kein Muss und fast noch schlimmer als die C++ - Geschichte.
    Ok, ich habe jetzt gesehen, dass es keine wirklich sinnvolle, sondern eher verwirrende Anwendungen für dieses "Feature" gibt. Danke für Eure Mithilfe. Für mich ist der Fall klar, deshalb mach ich hier dicht. Trotzdem ist es ja möglich, Antworten zu posten.

    cheerio,
    -ds-

  • Unsauberer Programmierstil kommt da nicht raus. Aber man muss sich nicht mehr Gedanken über die Ownership der HeapObjecte machen. Die Erfahrung hat gezeigt dass das auch bei erfahrenen Programmieren immer wieder Probleme mit den Memoryallocations macht. Deshalb setzen mittlerweile alle neueren Programmiersprachen auf einen GC. Das hat natuerlich einen Einfluss auf die Geschwindigkeit - aber auch auf die Robustheit der Programme die GC benutzen.


  • Das hat natuerlich einen Einfluss auf die Geschwindigkeit ...


    Genau - die Effizienz bleibt erheblich auf der Strecke! :(

    Die ist aber bei technischen Programmen sehr wichtig. Wer etwas komplexeres schreibt, braucht sich nicht wundern, wenn die CPU irgendwann voll ausgelastet ist, obwohl es vielleicht nur 20 % Last sein müssten.

    Durchschnittlich kann man davon ausgehen, daß ein pures C Programm ca. 6x schneller läuft als z.B ein Python Programm.

    Gruß, mmi

  • Um nochmal auf das ursprüngliche Problem zurückzukommen:


    Ausgabe des Scripts:

    Code
    ('one', 'two') <type 'tuple'>
    one - two
    <type 'str'> <type 'str'>
    one - two

    Wie man hier sieht, handelt es sich eigentlich um ein Missverständnis. Auch Python gibt nur einen einzigen Rückgabewert zurück, nämlich ein Tupel! Dieses Tupel enthält zwei Strings. Also ist es auch Unterschied zu C, wo ich ja auch einen struct von verschiedenen Werten zurückgeben kann.

    Die Verwirrung kommt nur daher, dass Python mehrere hinter einem return aufgelistete Werte automatisch in ein Tupel packt und bei Zuweisung an eine Auflistung von Variablen das Tupel auch wieder automatisch entpackt.

    Code
    def Funktion():
        return 1, 2, 3    # gibt eigentlich (1, 2, 3) zurück
    
    
    a = Funktion()        # a = (1, 2, 3), type(a) == 'tuple'
    
    
    a, b, c = Funktion()  # Tupel wird automatisch entpackt --> a = 1, type(a) == 'int'


    Auch wenn eine Funktion ja eigentlich immer nur genau eine wohldefinierte Aufgabe erledigen soll, gibt es für dieses Verhalten viele praktische Anwendungsfälle. Man sollte sich halt nicht unbedingt verschiedene Dinge zurückgeben lassen, die eigentlich nichts miteinander zu tun haben.

    Einmal editiert, zuletzt von Singletrailer (9. März 2014 um 21:49)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!