7. Funktionen
In den vorherigen Kapiteln haben wir immer wieder auf Funktionen zurückgegriffen,
welche uns von Python zur Verfügung gestellt wurden. Wenn du beispielsweise den
Befehl len("Haus")
eingibst, bekommen wir von der Funktion
len()
den Rückgabewert 4
zurück. Dieser Wert ändert sich
natürlich, wenn ein anderes Argument als "Haus"
der Funktion übergeben
wird.
In diesem Kapitel besprechen wir, wie man selber solche Funktionen definieren kann. Es gibt verschiedene Gründe, warum es Sinn macht Funktionen zu definieren.
1. Mehrer hintereinander ausgeführte Anweisungen können unter einem Namen zusammengefasst werden. Es kann also als Strukturierungselement angesehen werden, das eine Menge von Anweisungen gruppiert.
2. Ein längeres Programm erhält durch Funktionen eine Struktur, welche helfen kann, den Code besser lesen und verstehen zu können.
3. Ein Funktionsname kann dabei helfen zu verstehen, was das Unterprogramm berechnet oder ausführt.
4. Muss eine Codesequenz mehr als einmal ausgeführt werden, so braucht man nur den Funktionsnamen aufzurufen (Vermeidung von Codeduplizität).
Betrachten wir das folgende Beispiel:
1from random import randint
2
3eingabe = int(input("Gib eine positive ganze Zahl an: "))
4
5liste = []
6for i in range(eingabe):
7 liste.append(randint(0,100))
8
9result = 0
10for i in range(eingabe):
11 result = result + liste[i]
12
13result = result / len(liste)
14
15print("Das Ergebnis lautet " + str(result) + ".")
Es benötigt eine Weile um zu verstehen, was das Programm genau macht. Bei genauerem Hinsehen sieht man, dass die paar Codezeilen aus zwei Hauptteilen besteht: Zuerst wird eine zufällig, ganzzahlige Liste erstellt und danach deren arithmetischen Mittelwert berechnet.
Lagern wir diese zwei Hauptteile in Funktionen mit geeigneten Namen aus, so wird das Programm verständlicher zu lesen sein, ohne sich um programmtechnische Details kümmern zu müssen:
1from random import randint
2
3def zufallsliste_erstellen(eine_zahl):
4 liste = []
5 for i in range(eine_zahl):
6 liste.append(randint(0,100))
7 return liste
8
9def berechne_mittelwert(eine_liste):
10 result = 0
11 for i in range(len(eine_liste)):
12 result = result + eine_liste[i]
13
14 result = result / len(eine_liste)
15
16 print("Das Ergebnis lautet " + str(result) + ".")
17
18# Hauptprogramm
19eingabe = int(input("Gib eine positive ganze Zahl an: "))
20zufallsliste = zufallsliste_erstellen(eingabe)
21berechne_mittelwert(zufallsliste)
Das Programm besteht nun wesentlich aus den Zeilen 19-21. Nur das Lesen dieser 3 Zeilen reicht aus, um zu verstehen, was das gesamte Programm macht. Die Anweisungen für das Erstellen einer Zufallsliste und die Berechnung des arithmetischen Mittelwertes wurden in Funktionen ausgelagert (siehe Zeile 1-17).
Zusätzlich stehen die Möglichkeiten der beiden Funktionen zu jedem
beliebigen Zeitpunkt später im Programm wieder zur Verfügung.
D.h. alleine durch den Funktionsaufruf
zufallsliste_erstellen()
kann jederzeit im Programm wieder eine
Zufallsliste erstellt werden, ohne die ganzen Anweisungen nochmals
aufschreiben zu müssen.
Betrachten wir nun im Detail, wie Funktionen in Python erstellt werden können.
7.1. Eine Funktion ohne Rückgabewert definieren
Mit dem Keyword def
führen wir eine neue Funktion ein. Nach
der Anweisung def
steht der Name der Funktion, gefolgt von
runden Klammern ()
. In der Klammer ()
werden die Argumente, falls
welche verlangt, aufgelistet. Zum Schluss kommt noch der obligate Doppelpunkt
:
. Die darauffolgende Zeilen müssen wie üblich eingerückt sein, ansonsten
gehören sie nicht mehr zur Funktion.
Hier ein Beispiel einer Funktion, welche eine Zahl als Übergabeparameter erwartet. Die Funktion selber multipliziert die Eingabe mit 2 und gibt das Resultat auf der Konsole wieder aus.
1def mit_zwei_multiplizieren(eingabe):
2 eingabe = 2*eingabe
3 print("Verdopple ich diese Zahl, so erhalte ich ",eingabe)
4
5
6zahl = int(input("Gib eine ganze Zahl ein: "))
7mit_zwei_multiplizieren(zahl)
8zahl = int(input("Gib eine weitere ganze Zahl ein: "))
9mit_zwei_multiplizieren(zahl)
10
11print("Danke für die Eingabe.")
Jedes Mal wenn im Programm die Funktion mit_zwei_multiplizieren()
aufgerufen wird, wird der Codeblock bei der Definition der Funktion
(in unserem Beispiel Zeile 2 und 3) ausgeführt.
Natürlich können der Funktion auch mehr als nur ein Argument übergeben werden.
1# Eingabe: Längen des Rechtecks
2# Ausgabe in der Konsole: Fläche des Rechtecks
3def flaeche_rechteck(a,b):
4 print("Die Fläche des Rechtecks ist "+str(a*b)+".")
Eine mögliche Ausgabe könnte dann folgendermassen aussehen:
>>> flaeche_rechteck(3,7)
Die Fläche des Rechtecks ist 21.
>>> flaeche_rechteck(2.3,5.1)
Die Fläche des Rechtecks ist 11.729999999999999.
7.1.1. Aufgaben
Erstelle eine Funktion, welche einen String als Argument erwartet und den ersten und letzten Buchstaben des Strings ausgibt.
Schreibe eine Funktion
summe()
, welche für die Eingabe einer Zahl \(n\) folgendes Resultat ausgibt:\[\text{summe} := 1 + 2 + \dots + n\]Es sollte dann z.B. folgendermassen aussehen:
>>> summe(4) 10 >>> summe(100) 5050
Definiere eine Funktion
teilermenge(zahl)
, welche die Menge der Teiler vonzahl
ausgibt. Zum Beispiel:>>> teilermenge(24) [1, 2, 3, 4, 6, 8, 12, 24]
7.2. Eine Funktion mit Rückgabewert definieren
Unsere selbst geschriebenen Funktionen von oben haben bisher die Resultate lediglich auf der Konsole ausgegeben. Jedoch kann es sein, dass die Ergebnisse für den weiteren Programmverlauf gebraucht und weiter verarbeitet werden müssen. In solchen Fällen macht es Sinn Funktionen zu definieren, welche mir ein Ergebnis zurückgeben, wie z.B.
>>> len("Haus")
4
Nehmen wir das gleiche Beispiel von oben:
1# Eingabe: Längen des Rechtecks
2# Ausgabe in der Konsole: Fläche des Rechtecks
3def flaeche_rechteck(a,b):
4 print("Die Fläche des Rechtecks ist "+str(a*b)+".")
Diese Funktion gibt auf der Konsole die Fläche des Rechtecks mit Längen
a
und b
aus. Möchte man das Ergebnis nicht ausgeben, sondern z.B. für
eine Weiterverarbeitung zurückgeben, so kann dies mit der return
Anweisung gemacht werden:
1def flaeche_rechteck(a,b):
2 return a*b
Nun kann das Ergebnis der Funktion flaeche_rechteck()
in
einer Variable gespeichert und weiter
verwendet werden.
>>> a = flaeche_rechteck(2,5)
>>> a
10
Bemerkung
Eine Funktion mit einem return
Statement kommt dem
Konzept einer Funktion im Sinne der Mathematik sehr nahe:
wobei
Mehr zum Thema Funktionen findest du in der Dokumentation unter
https://docs.python.org/3.2/tutorial/controlflow.html#defining-functions
7.2.1. Aufgaben
In den vorherigen Kapiteln hast du die Fakultät in den Aufgaben bereits kennengelernt.
\[n! := n \cdot (n-1) \cdot(n-2) \cdots 3 \cdot 2 \cdot 1\]Definiere eine Funktion
fakultaet(zahl)
, welche die Fakultät vonzahl
berechnet und als Ergebnis zurückgibt.Schreibe nun ein kleines Programm, welches zwei natürliche Zahlen einliest und jeweils deren Fakultät berechnet und ausgibt.
Schreibe eine Funktion
quersumme(zahl)
, welche die Quersumme vonzahl
berechnet und zurückgibt.Schaue dir die folgende Funktion an und überlege, was das Ergebnis sein könnte.
1def meine_funktion(a,b): 2 while b != 0: 3 t = a%b 4 a = b 5 b = t 6 return a
Hast du eine Vermutung? Teste sie an einigen Beispielen:
>>> meine_funktion(12,16) >>> meine_funktion(1,16) >>> meine_funktion(8,16) >>> meine_funktion(8,21) >>> meine_funktion(18,21) >>> meine_funktion(27,36)
Welche der folgenden Definitionen sind zulässig? Welche nicht und wieso? Überlege zuerst und tippe es danach zur Kontrolle ein.
Definition 1:
def print(): print("Hallo Welt")
Definition 2:
def print1() print("Hallo Welt")
Definition 3:
def print1(): print("Hallo Welt")
Definition 4:
def print1(): print("Hallo Welt")
Schreibe zwei Funktionen mit folgender Funktionalität:
dez_to_bin(dezzahl)
: Die Funktion wandelt die Dezimalzahldezzahl
in die entsprechende Binärzahl um. [1]bin_to_dez(binzahl)
: Die Funktion wandelt die Binärzahlbinzahl
in die entsprechende Dezimalzahl um.Teste deine beiden Funktionen indem du sie mit den von Python zur Verfügung gestellten Funktionen vergleichst (
bin()
undint()
):# Konvertiert eine Dezimalzahl in eine Binärzahl >>> bin(24) '0b11000' # Konvertiert eine Binärzahl in eine Dezimalzahl >>> int('11000',2) 24
7.3. Mehrere Rückgabewerte
Bis jetzt haben unsere Funktionen immer nur einen Wert zurückgeben. Mit Python ist es überhaupt kein Problem, auch Funktionen zu definieren, welche mehr als einen Wert zurückgeben. Hier ein Beispiel dazu:
1def add_multiply(zahl1, zahl2):
2 return zahl1+zahl2, zahl1*zahl2
3
4a = add_multiply(4,10)
5print(a, a[0], a[1])
6
7a, b = add_multiply(4,10)
8print(a, b)
Dieses Programm gibt die Summe und das Produkt zweier
Zahlen (hier zahl1
und zahl2
) zurück.
Folgende Ausgabe erhalten wir auf der Konsole:
(14, 40) 14 40
14 40
Wir sehen bei der Zuweisung in Zeile 4, dass
die mehreren Rückgabewerte als Tupel der einen Variable a
übergeben werden. Man kann aber auch jeden Rückgabewert einer einzigen Variablen
zuweisen, so wie es in Zeile 7 gemacht wurde.
7.4. lambda
-Operator
Der lambda
-Operator bietet eine Möglichkeit anonyme Funktionen,
also Funktionen ohne Namen, zu schreiben und zu benutzen.
Anstelle des Keywords def
gebrauchen wir das Keyword
lambda
. Sie können, wie normal definierte Funktionen,
eine beliebe Anzahl von Parametern haben, führen Befehle aus und können
einen Rückgabewert liefern.
Die Syntax sieht folgendermassen aus:
lambda [arg1 [,arg2,.....argn]]:expression
Das nächste Beispiel zeigt den Unterschied zwischen einer normalen Funktion und einer lambda Funktion:
>>> def f(x): return x**2
>>> print(f(8))
64
>>> g = lambda x: x**2
>>> print(g(8))
64
Wir sehen, dass die beiden Funktionen f
und g
genau das gleiche
ausführen und auf die gleiche Weise benutzt werden können.
Sie unterscheiden sich hier lediglich in der Definition.
Wie aber der Name (anonyme Funktionen) schon sagt,
müssen wir einem lambda
-Ausdruck
keinen Namen zuweisen, was wir am folgenden Beispiel gut sehen:
>>> (lambda x: x**2)(8)
64
Der lambda
-Operator kann dann gut gebraucht werden,
wenn beispielsweise eine Funktion als Argument einer weiteren Funktion
übergeben werden soll
und man diese erste Funktion nachher nicht mehr braucht.
Schauen wir dazu folgendes Beispiel an:
1def temp_funktion(x): 2 return x + 42 3 4def make_list(f,groesse): 5 ergebnis = [] 6 for i in range(groesse): 7 ergebnis.append(f(i)) 8 return ergebnis 9 10a = make_list(temp_funktion, 5) 11print(a)
Diese Programm liefert dann folgenden Output:
[42, 43, 44, 45, 46]
Nehmen wir an, dass die Funktion temp_funktion()
in einem späteren Programmverlauf nie mehr gebraucht wird.
So können wir uns die Namensvergabe sparen und ändern denn Code
folgendermassen:
1def make_list(f,groesse): 2 ergebnis = [] 3 for i in range(groesse): 4 ergebnis.append(f(i)) 5 return ergebnis 6 7a = make_list(lambda x: x + 42, 5) 8print(a)
Dieses Programm hat den gleichen Output wie das erste, jedoch mussten wir nicht eine Funktion definieren, welche wir später sowieso nicht gebraucht hätten.
7.4.1. Aufgaben
Welche der folgenden Eingaben sind zulässig? Welche nicht und wieso? Wie müsste es richtig sein? Überlege zuerst und tippe es danach zur Kontrolle ein.
>>> a = lambda arg1, arg2: arg1 + arg2 >>> print(a(0,2))
>>> a = (lambda arg1, arg2: arg1 + arg2)(0,2) >>> print(a(0,2))
>>> a = lambda arg1, arg2: arg1 + arg2 >>> print(a(2+2))
>>> a = lambda arg1, arg2: arg1 + arg2 >>> b = lambda x: a(2, x) >>> print(b(3,4))
Gegeben ist folgendes Programm:
1def f2(d): 2 return 2**d 3 4def f3(d): 5 return 3**d 6 7def f5(d): 8 return 5**d 9 10def f7(d): 11 return 7**d 12 13def add_function(f,g): 14 return f(2) + g(2) 15 16print(add_function(f2, f3)) 17print(add_function(f5, f7))
Schreibe das Programm mit dem
lambda
-Operator so um, dass die Zeilen 1-12 weggelassen werden können, jedoch der gleiche Output produziert wird.
Footnotes