Mehrere Funktionen in einer anderen Funktion abrufen.

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.
Slim Shady
User
Beiträge: 10
Registriert: Dienstag 15. November 2016, 22:36
Wohnort: Wuppertal

Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Slim Shady » Mittwoch 11. Januar 2017, 19:54

Hallo,

Ich bin gerade dabei, mir mit einem kleinen textbasierten Übungsspielchen Python ein wenig näher zu bringen, und in diesem Textspiel gibt es einen Hauptteil, quasi die "Story", und viele kleine Unterprogramme für den Levelneustart oder für den Spielstart. Wie gesagt, nur ein bisschen Spielerei. Als ich heute aber mein Ladezeiten-Codeschnipsel auch dann einsetzen wollte, wenn man das Spiel zum ersten mal startet, habe ich den Code auch noch in eine Funktion gepackt, damit ich ihn nicht zweimal schreiben muss und leichter verändern kann.

Allerdings funktioniert er nicht so wie er soll, der Codeschnipsel für den Neustart sieht so aus:

  1. def reverse(): #Die Neustart-Funktion des Spiels
  2.     userinput = input("Do you want to play again? (y/n):")
  3.  
  4.     if userinput == "yes":
  5.         load_times()
  6.         Klippe()   #Hier wird das Spiel neu gestartet
  7.         reverse()  
  8.  
  9.     else:
  10.         print ("Shutting down our hero...")
  11.         sleep(2.5)
  12.         print ("Goodbye")
  13.         exit()
  14.  
  15. reverse()


Wobei hier Klippe() das eigentliche Spiel ist, auch als Funktion, und reverse() startet die Funktion innerhalb der Funktion noch einmal neu, falls der Spieler danach noch einmal neu starten möchte. Ich kann das bestimmt in eine Klammer machen, aber ich stehe noch ziemlich am Anfang und hätte erstmal keine Idee, wie ich das realisieren könnte.
Hier ist übrigens nochmal der Inhalt der load_times()-Funktion. Nichts spannendes, aber der Vollständigkeit zum Zweck:

  1. def load_times():
  2.                print ("Reinitialising the programm...")
  3.                sleep(3)
  4.                print ("Catching the turtle...")
  5.                sleep(1)
  6.                print ("Deleting System32...")
  7.                sleep(2)
  8.                print ("Programm successfully loaded...")
  9.                sleep(1)
  10.  
  11. load_times()


Wenn ich das Programm ausführe, klappt alles wunderbar, aber wenn ich (bzw das Programm) in der Neustart-Funktion die Ladezeitenfunktion abrufe, dann gibt er mir die Fehlermeldung aus, das load_times() nicht definiert sei.

Kann ich nicht mehrere Funktionen hintereinander in einem Programm abrufen?
Oder woran hakelt es?

Über Hilfe wäre ich sehr dankbar.
:!: :?:
nezzcarth
User
Beiträge: 413
Registriert: Samstag 16. April 2011, 12:47

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon nezzcarth » Mittwoch 11. Januar 2017, 20:12

Das ist schwer zu sagen, ohne den gesamten Quelltext zu sehen. Die Fehlermeldung deutet darauf hin, dass du die beiden Funktionen (ohne Rückgabewerte sind sie das meiner Ansicht nach eigentlich nicht) nicht auf Modulebene definiert, sondern irgendwo "verbuddelt" hast. An sich kannst du natürlich Funktionen aus anderen Funktionen aufrufen -- auch mehrere. Aber diese müssen für einander sichbar sein.

Weiterhin ist der rekursive Aufruft von reverse nicht so gut, weil Python ein Rekursionstiefenlimit hat; irgendwann ist's vorbei mit spielen :)

So in der Richtung sollte es funktionieren:

  1. #!/usr/bin/env python3
  2. import time
  3.  
  4.  
  5. def klippe():
  6.     print('Klippe.')
  7.  
  8.  
  9. def load_times():
  10.     print ("Reinitialising the programm...")
  11.     time.sleep(3)
  12.     print ("Catching the turtle...")
  13.     time.sleep(1)
  14.     print ("Deleting System32...")
  15.     time.sleep(2)
  16.     print ("Programm successfully loaded...")
  17.     time.sleep(1)
  18.  
  19.  
  20. def main():
  21.     while True:
  22.         load_times()
  23.         klippe()
  24.         answer = input('Again? (y/n) ')
  25.         if answer.lower() not in {'y', 'yes'}:
  26.             break
  27.  
  28.  
  29. if __name__ == '__main__':
  30.     main()
Slim Shady
User
Beiträge: 10
Registriert: Dienstag 15. November 2016, 22:36
Wohnort: Wuppertal

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Slim Shady » Mittwoch 11. Januar 2017, 20:20

Hmm, so sieht er tatsächlch besser aus, allerdings drängen sich mir da noch einige Fragen auf:

Was ist ein Rekursionstiefenlimit? Heißt das, Funktionsaufrufe endlich?

Und was bedeutet der letzte Codeschnipsel von Zeile 26 und 27, den kenne ich zwar schon, weiß aber nicht was er macht oder wie man ihn einsetzt.
:!: :?:
Sirius3
User
Beiträge: 6667
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Sirius3 » Mittwoch 11. Januar 2017, 21:03

@Slim Shady: Rekursion ist, wenn sich eine Funktion immer wieder selbst aufruft. Passiert das sehr oft, kann das ein Fehler sein. Daher gibt es eine Limit um solche Fehler einfacher entdecken zu können. So wie Du Rekursion eingesetzt hast, würde ich das auch als Fehler ansehen. Die if-Zeile in der vorletzten Zeile sorgt dafür, dass main nur aufgerufen wird, wenn die Python-Datei als Programm aufgerufen wird und nicht, wenn die selbe Datei als Modul importiert wird. Damit kann man solchen Code flexibler einsetzten und Tests durchführen.
Slim Shady
User
Beiträge: 10
Registriert: Dienstag 15. November 2016, 22:36
Wohnort: Wuppertal

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Slim Shady » Donnerstag 12. Januar 2017, 09:43

Hm, ok, aber warum hast du hinter deine Funktionen nicht das hier gemacht:

  1. def main():
  2.     print ("main")
  3.  
  4. main()


Was ich meine, warum fehlt das main() am Ende der Funktion? Braucht man das nicht?
:!: :?:
BlackJack

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon BlackJack » Donnerstag 12. Januar 2017, 09:55

@Slim Shady: Es steht doch ein ``if __name__ == '__main__': main()`` da. Oder fragst Du etwa warum nicht hinter *jeder* Funktion nicht auch gleich ein Aufruf der gerade definierten Funktion steht? Dann würde ich sagen haben wir Dein Problem gefunden, und ich würde Dich fragen wozu das gut sein sollte.
Benutzeravatar
Kebap
User
Beiträge: 355
Registriert: Dienstag 15. November 2011, 14:20
Wohnort: Dortmund

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Kebap » Donnerstag 12. Januar 2017, 12:48

Slim Shady hat geschrieben:Code in eine Funktion gepackt, damit ich ihn nicht zweimal schreiben muss und leichter verändern kann.


Hallo Slim Shady, willkommen bei Python und im Forum! Grundsätzlich ist das die richtige Idee und alle machen das so, weil es genau diese Vorteile bietet. Vielleicht schaust du dir mal ein paar andere Programme hier im Forum an, wie es im Detail abläuft. Es sollte eigentlich keine Probleme geben, eine Funktion mehrfach aufzurufen. Diese sollte dann aber auch irgendwann enden und wieder zurückspringen, ggf. gibt sie dabei einige Werte zurück, und sollte jedenfalls nicht ihrerseits immer weiter neue Funktionen aufrufen.
MorgenGrauen: 1 Welt, >12 Gilden, >85 Abenteuer, >1000 Waffen und Rüstungen,
>2500 NPC, >16000 Räume, >170 freiwillige Programmierer, einfach Text, seit 1992.
BlackJack

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon BlackJack » Donnerstag 12. Januar 2017, 13:42

@Slim Shady: Noch als Tipp um sich zu ”zwingen” das mit den Funktionen richtig zu machen: Verzichte auf die `exit()`- bzw. `sys.exit()`-Funktion. Die sollte man nur verwenden wenn man etwas anderes als 0 als Rückgabecode des Programms an das Betriebssystem übergeben will. Und dann auch nur ganz weit oben in der Aufrufhierarchie. Eigentlich nur direkt im ersten und einzigen Aufruf der Hauptfunktion des Programms; maximal eine Aufrufebene tiefer.

Wenn man nicht explizit etwas an den Aufrufer des Programms zurückgeben will über den Rückgabecode, dann kann man den Kontrollfluss im Programm immer so strukturieren, dass der das ”natürliche Ende” erreicht. Also so, dass einfach kein Code mehr zum Ausführen da ist und das Programm deshalb beendet wird. Ein `exit()`-Aufruf ist in so einem Fall IMHO eine unsaubere Abkürzung, weil man dann auf Kosten der Nachvollziehbarkeit Nachdenken und Strukturieren des Codes weggelassen hat. Zudem macht `exit()` Funktionen schlecht testbar und wiederverwendbar und nimmt dem Aufrufer die Möglichkeit anders zu reagieren als mit einem kompletten Programmabbruch.
Slim Shady
User
Beiträge: 10
Registriert: Dienstag 15. November 2016, 22:36
Wohnort: Wuppertal

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon Slim Shady » Freitag 13. Januar 2017, 17:04

Ok, ich habe eure Lösungsansätze mal ausprobiert, und es funktionert auch alles, allerdings fragt er jetzt nicht mehr nach, ob man das Spiel auch wirklich neustarten will. Und ich kriege das Problem irgendwie nicht in den Griff. Kann mir da jemand von euch helfen. Muss ich das in die Iteration integrieren?
:!: :?:
Benutzeravatar
pyHoax
User
Beiträge: 84
Registriert: Donnerstag 15. Dezember 2016, 19:17

Re: Mehrere Funktionen in einer anderen Funktion abrufen.

Beitragvon pyHoax » Freitag 13. Januar 2017, 17:34

Hallo Slim Shady,

Deine Fragen gehen doch sehr auf deine Implementation zurück, die wir nicht kennen.

Wenn du denkst das du in Zukunft öfters Dinge entwickeln und deine Arbeit mit anderen Personen Teilen willst solltest du darüber nachdenken dir einen Github Account zuzulegen.
Auf Github kannst du dir für deine Projekte Repositories anlegen die du dann mit dem ganzen I-Net oder auserwählten Usern auf Github teilen kannst.
Allerdings müsstest du das Versionkonrolltool 'git' beherrschen (leider eine Art von Kryptowissenschaft), ein Tool was in jedem Entwicklungsprojekt mit mehr als einer Person heutzutage Benutzt wird. Früher haben nur ambinionierte Projekte ein öffentliches Interface zu ihrer Codeverwaltung zugelegt, aber heutzutage ist Github unter Informatiker so üblich wie WhatsApp bei Mittelstufeschülern.

Der Vorteil liegt klar auf der Hand: Wir könnten deinen Code über Github einsehen und dir sogar Patches einstellen die du dann verwenden oder zurückweisen kannst.

Guß pyHoax

Wer ist online?

Mitglieder in diesem Forum: Bing [Bot]