Matroids Matheplanet Forum Index
Moderiert von matph
Informatik » Programmieren » Python: Manipulation einer globalen Liste innerhalb einer Funktion
Autor
Universität/Hochschule Python: Manipulation einer globalen Liste innerhalb einer Funktion
traveller
Senior Letzter Besuch: im letzten Monat
Dabei seit: 08.04.2008
Mitteilungen: 2689
  Themenstart: 2017-10-03

Hallo, Folgendes Programm: \sourceon Python liste = [] def funktion(n): if n == 0: return liste else: liste.append(n) funktion(n-1) print(funktion(5)) \sourceoff Dieses gibt mir "None" zurück. Meine Vermutung war, dass dies entweder mit der (natürlich unsinnigen) Manipulation der globalen Liste innerhalb des Programms oder mit der Rekursion zu tun hat. Füge ich jedoch oberhalb des return ein "print(liste)" ein, gibt mir dieses wie erwartet die Liste [5, 4, 3, 2, 1]. Wieso kann diese dann trotzdem nicht zurückgegeben werden?


   Profil
dromedar
Senior Letzter Besuch: vor mehr als 3 Monaten
Dabei seit: 26.10.2013
Mitteilungen: 5123
Wohnort: München
  Beitrag No.1, eingetragen 2017-10-03

Hallo traveller, im else-Zweig fehlt ein return: \sourceon Python liste = [] def funktion(n): if n == 0: return liste else: liste.append(n) return funktion(n-1) print(funktion(5)) \sourceoff Grüße, dromedar


   Profil
traveller
Senior Letzter Besuch: im letzten Monat
Dabei seit: 08.04.2008
Mitteilungen: 2689
  Beitrag No.2, vom Themenstarter, eingetragen 2017-10-03

Ok, damit klappt es, aber ich verstehe nicht ganz warum. Solange ich im else-Zweig lande, will ich doch die Funktion nur aufrufen und gar nichts zurückgeben. Erst wenn das Argument bei 0 angekommen ist, soll doch auch was zurückgegeben werden.


   Profil
dromedar
Senior Letzter Besuch: vor mehr als 3 Monaten
Dabei seit: 26.10.2013
Mitteilungen: 5123
Wohnort: München
  Beitrag No.3, eingetragen 2017-10-03

\quoteon(2017-10-03 01:56 - traveller in Beitrag No. 2) Erst wenn das Argument bei 0 angekommen ist, soll doch auch was zurückgegeben werden. \quoteoff Das, was die Funktion für $n=0$ zurückgibt, geht an den Aufrufer der Funktion. Das ist aber nur für den Fall, dass die Funktion aus dem print-Statement heraus mit $n=0$ aufgerufen wurde, dieses print-Statement. Sonst ist es die Funktion mit dem Argument $n=1$. Und die verwirft ohne return den erhaltenen Rückgabewert und liefert stattdessen None. PS Was Du in Deinem Startbeitrag von dem return in der rekursiven Funktion erwartest, ist, dass es den Wert nicht an die aufrufende Funktion, sondern gleich "ganz nach oben" weiterreicht. Ob so etwas in Python möglich ist, weiß ich nicht, aber prinzipiell könnte das so aussehen: \sourceon Scheme (define liste '()) (define (funktion n return-to-caller) (cond ((= n 0) (return-to-caller liste)) (else (set! liste (append liste (list n))) (funktion (- n 1) return-to-caller)))) (call-with-current-continuation (lambda (return-to-caller) (funktion 5 return-to-caller))) \sourceoff


   Profil
viertel
Senior Letzter Besuch: im letzten Quartal
Dabei seit: 04.03.2003
Mitteilungen: 27784
Wohnort: Hessen
  Beitrag No.4, eingetragen 2017-10-03

Es geht auch ohne globale Variable: \sourceon Python def funktion2(n): if n == 0: return [] else: liste2 = [n] liste2.extend(funktion2(n-1)) return liste2 \sourceoff


   Profil
dromedar
Senior Letzter Besuch: vor mehr als 3 Monaten
Dabei seit: 26.10.2013
Mitteilungen: 5123
Wohnort: München
  Beitrag No.5, eingetragen 2017-10-03

\quoteon(2017-10-03 12:23 - viertel in Beitrag No. 4) Es geht auch ohne globale Variable: \quoteoff Es sein denn, es ist das Ziel der Funktion, eine globale Variable zu manipulieren.


   Profil
viertel
Senior Letzter Besuch: im letzten Quartal
Dabei seit: 04.03.2003
Mitteilungen: 27784
Wohnort: Hessen
  Beitrag No.6, eingetragen 2017-10-03

Wir wissen doch alle, daß globale Variablen nach Möglichkeit zu vermeiden sind ;-)


   Profil
dromedar
Senior Letzter Besuch: vor mehr als 3 Monaten
Dabei seit: 26.10.2013
Mitteilungen: 5123
Wohnort: München
  Beitrag No.7, eingetragen 2017-10-03

\quoteon(2017-10-03 17:38 - viertel in Beitrag No. 6) Wir wissen doch alle, daß globale Variablen nach Möglichkeit zu vermeiden sind ;-) \quoteoff Im Startbeitrag wird eine konkrete Frage anhand eines konkreten Beispielprogrammschnipsels gestellt. Meiner Meinung nach sollte man sich auf diese Frage konzentrieren und nicht versuchen, alle möglichen Verbesserungsoptionen dieses Beispielprogrammschnipsels auszuleuchten.


   Profil
viertel
Senior Letzter Besuch: im letzten Quartal
Dabei seit: 04.03.2003
Mitteilungen: 27784
Wohnort: Hessen
  Beitrag No.8, eingetragen 2017-10-03

Wie es zu dem Programm im TS kam (Aufgabenstellung?) weiß ich natürlich nicht. Aber Tips für besseren Programmierstil weiterzugeben kann ja nicht schaden. Und für solche Probleme, die auch in sich geschlossen gelöst werden können, globale Variablen zu verwenden ist nun mal keine gute Idee. Leider wird das auch immer wieder in Programmierkursen „vorgelebt“ oder gar vorgegeben.


   Profil
__blackjack__
Aktiv Letzter Besuch: in der letzten Woche
Dabei seit: 23.09.2021
Mitteilungen: 27
  Beitrag No.9, eingetragen 2021-09-27 16:39

Wenn man schon eine globale Liste verändert, und ich finde das auch keine gute Idee, dann würde ich aber nicht sagen, dass da ein ``return`` fehlt, sondern da ist eines zu viel. Die Funktion sollte nicht die globale Datenstruktur ”zurückgeben”, die sie manipuliert. Ist auch ja auch ein völlig sinnloser Rückgabewert, da in jedem Aufruf die *selbe* Liste zurück zu geben, die von überhaupt nichts abhängig ist. Das Ding ist global verfügbar, also kann der Aufrufer ja auch einfach darauf zugreifen. \sourceon python liste = [] def funktion(n): if n > 0: liste.append(n) funktion(n - 1) funktion(5) print(liste) \sourceoff Einen ”direkten” Sprung aus einem tiefen Aufruf bzw. ein ``return`` über mehrere Aufrufebenen hinweg, so ähnlich wie das im Scheme-Beispiel von dromedar in Beitrag #3 steht, kann man sich in Python mit Ausnahmen basteln. \sourceon python class Return(Exception): def __init__(self, value): Exception.__init__(self) self.value = value def call_with_deep_return(function, *args, **kwargs): try: function(*args, **kwargs) except Return as return_: return return_.value raise RuntimeError(f"function {function} did not raise `Return`") liste = [] def funktion(n): if n <= 0: raise Return(liste) liste.append(n) funktion(n - 1) print(call_with_deep_return(funktion, 5)) \sourceoff


   Profil
traveller hat die Antworten auf ihre/seine Frage gesehen.
traveller hatte hier bereits selbst das Ok-Häkchen gesetzt.

Wechsel in ein anderes Forum:
 Suchen    
 
All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest © 2001-2021 by Matroids Matheplanet
This web site was originally made with PHP-Nuke, a former web portal system written in PHP that seems no longer to be maintained nor supported. PHP-Nuke is Free Software released under the GNU/GPL license.
Ich distanziere mich von rechtswidrigen oder anstößigen Inhalten, die sich trotz aufmerksamer Prüfung hinter hier verwendeten Links verbergen mögen.
Lesen Sie die Nutzungsbedingungen, die Distanzierung, die Datenschutzerklärung und das Impressum.
[Seitenanfang]