====== Funktionen ====== Mit dem Schlüsselwort ''def'' (für //define//) kann man Funktionen definieren. Wie man an den Beispielen unten sieht, ist die Syntax ähnlich wie bei Schleifen (''for'') und Bedingungen (''if''): Ein Doppelpunkt ist in der "Kopfzeile" nötig, der eigentliche Code der Funktion ist einzurücken. Funktionen nehmen einen oder mehrere oder auch gar keinen Wert als Input (man spricht auch von den Parametern der Funktion). Als Wert sind integer, string, Boolean etc. erlaubt. Funktionen können (müssen aber nicht) mit Hilfe des Schlüsselworts ''return'' einen Wert zurückgeben (so wie man das erwartet, wenn man an den Funktionsbegriff in der Mathematik denkt). Funktionen haben einerseits den Zweck, sonst mehrfach auftauchenden Code zu bündeln; andererseits dienen sie der besseren Struktur/Lesbarkeit des Programms. Verstehe die folgenden Programme. # Funktion mit einem Parameter def quadrat(x): return x*x print(quadrat(12)) # Dieses Beispiel zeigt, dass Funktion recht flexibel sind, was Parameter angeht: # Hier kann der Übergabeparameter sowohl eine Zahl als auch ein String sein. # (Viele andere Programmiersprachen sind weniger flexibel.) def quadrat(x): return 3*x print(quadrat(14)) print(quadrat("abc")) # Funktion mit zwei Parametern def addiere(x,y): return x + y print(addiere(2, 5)) # Funktion ohne Parameter def gib_text_aus(): print("Hallo Welt") gib_text_aus() print(gib_text_aus()) # Gibt eine Funktion wie hier keinen Wert mit "return" zurück, so gibt Python per Konvention den Wert "None" zurück. Implementiere die [[https://de.wikipedia.org/wiki/Fakult%C3%A4t_(Mathematik)|Fakultätsfunktion]] $n!$ und die [[https://de.wikipedia.org/wiki/Binomialkoeffizient|Binomialkoeffizientenfunktion]] $n \choose k$ in Python und teste sie, zum Beispiel durch Ausgabe des [[https://de.wikipedia.org/wiki/Pascalsches_Dreieck|Pascalschen Dreiecks]] (in möglichst schöner Formatierung!). Du kannst einer Funktion auch eine Liste als Parameter übergeben. Schreibe ein Programm, das dies ausnutzt! - Etwa ein Programm, das den Durschnitt einer Liste von Zahlen ausrechnet. Jemand hat versucht, ein Programm zu schreiben, dass alle Primzahlen kleiner-gleich ''n'' ausgibt, die Ausgabe ist aber falsch. Verbessere das Programm (es genügt, vier Zeichen (und eventuell Leerzeichen) zu ergänzen)! Bemerkung: Sobald die ''return''-Anweisung in einer Funktion aufgerufen wird, wird die weitere Ausführung der Funktion abgebrochen. (Hierbei steht ''sqrt(...)'' für "square root", Quadratwurzel und ''int(...)'' macht aus einer Kommazahl eine ganze Zahl.) # Fehlerhaftes Programm! n = 97 def ist_prim(x): for t in range(2, int(sqrt(x))): if x % t == 0: return False return True l = [] for i in range(2, n): if ist_prim(i): l.append(i) print(l) Funktionen können sich selbst aufrufen! Dies ist oftmals sehr hilfreich (siehe Abschnitt [[lehrkraefte:snr:informatik:python:rekursion|Rekursion]]). Ändere das folgende Programm so, dass es nach endlicher Zeit endet! Abbruch mit dem roten Achteck in der Menüleiste von Tigerjython. # Nicht endendes Programm (es sei denn, der Strom fällt aus oder der Computer verrottet oder # - was in Wirklichkeit eintritt - es gibt einen Laufzeitfehler, wie du sehen wirst.) def schreibe(n): print(n * "A" + ";") schreibe(n+1) print(n * "B" + ";") schreibe(1) print("Ende") Ersetze die Zeile ''schreibe(n+1)'' beispielsweise durch if n < 10: schreibe(n+1) ACHTUNG, ICH HATTE LEIDER ZUNÄCHST DAS AUSRUFEZEICHEN IN DER ZWEITEN ZEILE VERGESSEN! Versuche die folgende Definition der Fakultätsfunktion {{:lehrkraefte:snr:informatik:python:fakultaet-definition.png?300|}} in ein Programm zu übersetzen. Wenn dir das gelingt, hast du "selbst" entdeckt, was //Rekursion// ist: Eine Funktion, die sich selbst (oft auch mehrfach) aufruft - aber so, dass das Programm nicht unendlich lange läuft. Die obige Definition ist übrigens die sogenannte //induktive// oder //rekursive// Definition der Fakultätsfunktion. ====== Globale und lokale Variablen ====== Überrascht dich die Ausgabe des folgenden Programms? def test(): s = "Welt" print(s) s = "Hallo" test() print(s) Variablen haben Sichtbarkeitsbereiche (englisch //scope//). Bevor wir Funktionen kennengelernt hatten, war dies unwichtig: Alle Variablen waren sogenannte //globale// Variablen. Im obigen Beispiel gibt es einerseits die globale Variable ''s'' (mit wert "Hallo"), andererseits die //lokale// Variable ''s'' in der Funktion ''test''. Diese beiden Variablen tragen (aus didaktischen Gründen) denselben Namen, werden aber beim Ablauf des Programms vollkommen unabhängig voneinander behandelt - so als ob die eine Variable ''s1'' und die andere ''s2'' hiesse. Innerhalb der Funktion ist nur die lokale Variable ''s'' in dem Sinne sichtbar, dass man kann ihren Wert abrufen und ändern kann. Ausserhalb ist nur die globale Variable ''s'' sichtbar. * Lösche im obigen Programm den Befehl ''s = "Welt"'' und teste das Programm. * Füge diesen Befehl dann in der Funktion HINTER ''print(s)'' wieder ein und teste das Programm! Wir lernen daraus: Solange es keine lokale Variable gleichen Namens gibt, ist eine globale Variable wie ''s'' im Beispiel (= im ganzen Programm) lesbar zugänglich, kann aber innerhalb von Funktionen nicht verändert werden. Existiert eine lokale Variable gleichen Namens, so muss diese in ihrer Funktion zunächst initialisiert werden (etwa mit ''s = "Welt"''), bevor man auf sie zugreifen kann. Manchmal ist es jedoch sinnvoll, eine globale Variable auch innerhalb von Funktionen verändern zu können (wie es ja der Name global eigentlich nahelegt)((in vielen Programmiersprachen ist dies standardmässig möglich)). Dies geschieht, indem man am Funktionsbeginn mit dem Schlüsselwort ''global'' expliziert festlegt, dass auch dieser "Schreibzugriff" auf die Variable möglich ist: def test(): print(s) global s s = "Welt" print(s) s = "Hallo" test() print(s) In diesem Beispiel bedeutet der Befehl ''s = "Welt"'' also nicht wie zuvor "lege eine neue lokale Variable ''ss'' mit dem Wert "Welt" an. Stattdessen wird der globalen (mit ''global'' lokal veränderlich gemachten) Variablen ''ss'' der Wert "Welt" zugewiesen. Vermutlich ist es intuitiv klar, der Vollständigkeit halber sei aber erwähnt, dass lokale Variablen ausserhalb ihres Sichtbarkeitsbereichst nicht zugänglich sind in dem Sinne, dass ihr Wert nicht abrufbar ist: def test(): s = "Welt" print(s) test() if s == "Welt": print("Weltschmerz") # s = "Hallo" # print(s) Wenn man hier aber die ''if''-Kontrollstruktur durch die beiden auskommentierten Zeilen ersetzt, so funktioniert das Programm wieder: Nun gibt es aber wie oben zwei voneinander unabhängige Variablen mit dem Namen ''s''. ===== Einige Lösungsvorschläge ===== def fakultaet(x): wert = 1 for i in range(1, x + 1): wert = wert * i return(wert) print(fakultaet(5)) for k in range(10): print("%d! = %d" % (k, fakultaet(k))) ===== Link zur Kursseite ===== [[lehrkraefte:snr:informatik:glf21|Zur Kursseite]]