===== Funktionen =====
++++Links zu Online-Tutorials|
* Dreiteiliges Tutorial zum Thema Funktionen vom Kanal "Programmieren Starten":
* Funktionen: [[https://youtu.be/LQCfN5HS9xI]]
* Funktionen mit Parametern: [[https://youtu.be/af9ORp1Pty0]]
* Funktionen mit Rückgabewert: [[https://youtu.be/ehSP-sYoKCY]]
++++
Wir haben gesehen, dass man mit einer while-Schleife den gleichen Codeblock mehrfach hintereinander ausführen kann. Was ist nun aber, wenn man den gleichen Codeblock //nicht// direkt hintereinander, sondern an verschiedenen Orten im Code aufrufen möchte? Nach unserem jetztigen Wissensstand bleibt uns nur Copy-Paste! Gleichzeitig wissen wir aber, dass wir uns schlecht fühlen sollen, wenn wir dies machen! Damit wir uns nicht schlecht fühlen müssen, wurden **Funktionen** erfunden: Diese erlauben es uns, den gleichen Codeblock von verschiedenen Stellen im Code aufzurufen. Funktionen sind auch nützlich, um komplexe Programme in kleinere, leichter zu programmierende Teilprogramme zu zerlegen.
Beispiele:
* In einem Zahlenspiel wollen wir oft überprüfen, ob eine Benutzereingabe eine nicht-negative Zahl ist. Diese Überprüfung könnte man in eine Funktion `check_user_input(...)` 'aussourcen'.
* Du möchtest oft die gleiche Art Rechnung ausführen, z.B. eine lineare Gleichung lösen -> Funktion `linear_equation_solver(...)`
Übrigens hast du schon viele Funktionen kennengelernt - ohne dass du es wahrscheinlich gemerkt hast. Zum Beispiel ist die Funktion `forward(...)` für Turtles eine Funktion, die ein Turtle eine gewisse Anzahl Pixel vorwärts laufen lässt.
In Python wird eine Funktion wie folgt programmiert:
def name_der_funktion(PARAMETER): # Parameter sind optional
# Codeblock der Funktion
return # optional
* Das Schlüsselwort `def` leitet immer die Definition einer Funktion ein.
* Darauf folgt der **Funktionsname**. Typischerweise schreibt man diesen mit ausschliesslich Kleinbuchstaben und Underscores `_`.
* Direkt anschliessend werden `(`**runde Klammern**`)` geschrieben. Diese enthalten die **Parameter**. Das sind Werte, die an die Funktion übergeben werden. Funktionen können auch ohne Parameter definiert werden, die Klammern sind dann halt einfach leer.
* Nach einem **Doppelpunkt** `:`
* folgt der **Funktionskörper**, der den eigentlichen Code der Funktion beinhaltet. Dieser Code muss **eingerückt** sein.
* Eine Funktion kann (muss aber nicht) mit `return` etwas **zurückgeben**.
Nachdem du eine Funktion definiert hast, kannst du sie ganz einfach aufrufen. Dazu mehr in den Beispielen unten.
=== Beispiel 1: Funktion ohne Parameter und Rückgabewert ===
Die Funktion gibt einfach "Hallo du!" aus, wenn sie aufgerufen wird. Die ersten beiden Zeilen definieren die Funktion. Unten wird sie zweimal aufgerufen, dementsprechend wird 2x "Hallo du!" ausgegeben.
def say_hi():
print("Hallo du!")
say_hi()
say_hi()
=== Beispiel 2: Funktion mit Parameter und ohne Rückgabewert ===
Nun soll unsere Begrüss-Funktion persönlicher werden. Wir wollen sowohl Silvia wie auch Gabriele grüssen. Der Code dazu ist identisch, mit Ausnahme des Namens. Dazu können wir der Funktion ein **Argument** (hier: den Namen) übergeben. Dazu müssen wir die Funktion 'vorwarnen': In den runden Klammern schreiben wir einen Parameter hinein, hier `name` in `def say_hi(name)`. Dies sagt der Funktion, dass man ihr ein Argument übergeben muss. Wird der Funktionskörper ausgeführt, ist der Parameter `name` wie eine gewöhnliche Variable, die den Wert im Aufruf übergebenen Arguments trägt.
Beim ersten Funktionsaufruf unten hat `name` also den Wert `"Silvia"` und beim zweiten den Wert `"Gabriele"`.
def say_hi(name):
print("Hallo " + name + "!")
say_hi("Silvia")
say_hi("Gabriele")
=== Beispiel 3: Funktion ohne Parameter aber mit Rückgabewert ===
In einem Glücksspiel wollen wir oft einen Würfelwurf simulieren. Dazu wollen wir eine Würfelfunktion `wuerfle()` programmieren, die uns eine Zufallszahl von $1$ bis $6$ gibt:
import random
def wuerfle():
rand_nr = random.randint(1,6)
return rand_nr
print(wuerfle())
print(wuerfle())
print(wuerfle())
=== Beispiel 4: Funktion mit Parameter und mit Rückgabewert ===
Nun wollen wir auch andere Würfel (z.B. 12er-Würfel) simulieren können. Dazu führen wir einen Parameter ein, der den maximalen Wert des Würfels festlegt:
import random
def wuerfle(max_nr):
rand_nr = random.randint(1,max_nr)
return rand_nr
print(wuerfle(12))
print(wuerfle(12))
print(wuerfle(12))
In Realität ist es aber so, dass die meisten Würfel bis $6$ gehen. Wir können nun unser Leben einfacher machen, indem wir den Parameter `max_nr` mit einem **Vorgabewert** ausstatten:
import random
def wuerfle(max_nr=6):
rand_nr = random.randint(1,max_nr)
return rand_nr
print(wuerfle(12)) # 12er-Wuerfel
print(wuerfle()) # 6er-Wuerfel, verwendet Vorgabewert
Der erste Funktionsaufruf simuliert natürlich einen 12er-Würfel. Der zweite einen 6er-Würfel: Da kein Argument für den Parameter `max_nr` übergeben wird, wird der Vorgabewert (`max_nr=6`) verwendet. Hier ist es üblich, //keinen// Abstand links und rechts vom Operator zu machen.
==== Aufgaben E ====
**Vorwissen:**
* [[gf_informatik:funktionen|Funktionen]]
* Bis und mit Beispiel 2 "Funktion mit Parameter und ohne Rückgabewert"
Bei diesen Aufgaben geht es um folgendes:
* Verstehen, was Funktionen sind und wozu sie nützlich sind
* einfache Funktionen programmieren
=== Aufgabe E1 ===
**Nette Begrüssung:** Schreibe eine Funktion, der man den Namen und den Wohnort einer Person als Argumente übergibt. Die Funktion begrüsst diese Person dann ganz herzlich. Beispiel: "Hallo, mein lieber Oskar aus Amriswil, ich wünsche dir einen ganz tollen Tag!"
=== Aufgabe E2 ===
Schreibe eine Funktion `head_or_tail()`, die einen Münzenwurf simuliert. Zufällig soll Kopf oder Zahl ausgewählt und ausgegeben werden.
++++Tipps:|
Erzeuge mithilfe des `random`-Moduls eine [[gf_informatik:programmieren_ii#zufallszahlen|Zufallszahl]] ($1$ oder $2$). Falls die Zufallszahl $1$ ($2$) ist, gibst du "Zahl" ("Kopf") aus. Verwende dazu eine Verzweigung.
++++
=== Aufgabe E3 ===
Schreibe eine Funktion `fortune_cookie()`, die ein Glückskeks-Spruch-Generator ist: Jedesmal wenn die Funktion aufgerufen wird, wird zufällig einer von mehreren Sprüchen ausgewählt und ausgegeben. Erfinde selber Sprüche oder klaue sie dreist aus dem Internet.
Rufe die Funktion auf.
++++Tipps:|
Ähnlich wie Münzwurf-Funktion oben. Bestimme wieder eine Zufallszahl (z.B. im Bereich $1-5$, falls du fünf Sprüche hast). Falls die Zufallszahl $2$ ist, gibst du den zweiten Spruch aus. Verwende dazu eine if-elif-...-else-Verzweigung.
Simuliere nun 20 Münzenwürfe.
++++
=== Aufgabe E4 ===
TurtleGraphics: Schreibe eine Funktion `square(x)`, die eine Zahl $x$ als Argument entgegen nimmt und ein Quadrat mit dieser Länge zeichnet.
=== Aufgabe E5 ===
Schreibe folgende Funktionen:
* `square(x,y,l)`: Zeichnet Quadrat mit Seitenlänge l, startend an Position $(x,y)$
* `circle(x,y,r)`: Zeichnet Kreis mit Radius r, startend an Position $(x,y)$
* `rectange(x,y,a,b)`: Zeichnet Rechteck mit Seitenlängen a und b, startend an Position $(x,y)$
* `triangle(x,y,l)`: Zeichnet gleichseitiges Dreieck mit Seitenlänge l, startend an Position $(x,y)$
* Funktion für selbst gewählte geometrische Figur
Mache nun moderne Kunst, indem du diese Funktionen aufrufst.
**Challenge (optional):** Erstelle mit möglichst vielen Zufallswerten moderne Kunst. Ziel: Kunst von deinem Programm soll besser und schöner sein als die vom Programm der Lehrperson!
Vom Zufall abhängen können z.B. folgende Werte:
* Anzahl, wie oft jede Funktion aufgerufen wird.
* Position von Figuren
* Grössen von Figuren
* Drehung von Figuren
* Farben (Stift- und Füllfarbe), dazu kannst du den Funktionen weitere Argumente übergeben
Tipps:
* Es lohnt sich, z.B. eine Funktion `draw_random_shape()` zu definieren, die dann zufällig eine der Formen zeichnet.
* Du kannst auch weitere Funktionen definieren, die dir das Leben erleichtern.
++++Lösungen Aufgaben E|
==== Aufgaben E ====
=== Aufgabe E1 ===
def greetings(name,residence):
print("Hallo, mein(e) liebe(r) " + name + " aus " + residence + ". Ich wünsche dir einen ganz tollen Tag!")
greetings("Fritz","Romanshorn")
greetings("Monika","Amriswil")
=== Aufgabe E2 ===
import random
"""
Wichtig: Die Ermittlung der Zufallszahl mit randint und die Verzweigung (Kopf oder Zahl) muss IN der Funktion gemacht werden, nicht ausserhalb!
"""
def head_or_tail():
r = random.randint(1,2)
if r == 1:
print("Head!")
else:
print("Tail!")
head_or_tail()
head_or_tail()
=== Aufgabe E3 ===
import random
def fortune_cookie():
r = random.randint(1,3)
if r == 1:
print("Spruch 1")
elif r == 2:
print("Spruch 2")
else:
print("Spruch 3")
=== Aufgabe E4 ===
from turtle import *
turi = Turtle()
turi.hideturtle()
turi.speed(1000)
def square(l):
i = 0
while i < 4:
turi.forward(l)
turi.right(90)
i = i + 1
square(50)
square(100)
square(150)
square(200)
=== Aufgabe E5 ===
from turtle import *
t = Turtle()
t.hideturtle()
def square(x,y,l):
t.teleport(x,y)
i = 0
while i < 4:
t.fd(l)
t.right(90)
i = i + 1
def circle(x,y,r):
t.teleport(x,y)
t.circle(r)
def rectangle(x,y,a,b):
t.teleport(x,y)
i = 0
while i < 2:
t.fd(a)
t.right(90)
t.fd(b)
t.right(90)
i = i + 1
def triangle(x,y,l):
t.teleport(x,y)
i = 0
while i < 3:
t.fd(l)
t.right(120)
i = i + 1
square(-200,-300,150)
circle(0,150,40)
rectangle(-150,50,20,100)
triangle(100,150,40)
[[https://webtigerpython.ethz.ch/?code=NobwRAdghgtgpmAXGGUCWEB0AHAnmAGjABMoAXKJMNGbAewCcyACBqCYumAHQgDMGXZmQCuTADZxmNek2YAqXiwC8zACpiykgBQBKJZgAWaYnFES4egwGdscOMW0BGAAwv9EXqb7NrARxEoBksADwJcAnFdRF5mOOFMMjhJWTJtMNwPeOlmVRdY-IB3Y0kcgB5mABYYiGzsskw-RyiCuoSGNABzQzSATndWurRcnIBqZideLzgfAGM0BlmdDIIGaMGGpJTGNIys-Ib5xZ01qY4Z1jhZighO5fCCKAIAI3Xag8TkuFT08P244Z5QbFNClYYVABMNTacQaTW0UH-dQaHW6fQG7zacMcr0G9UwqJ62n6SOygLGEzO3mEHXYd1CDyi0I-W2-O1-mUG5PymOYILBzAqAGZmVjGs1SR9CWknBCMTCcqphuNJp5zj42BwuAB9WZ0cSMbRkTW2IJwCBkZQAMSg4mscDe2WCxBGms4MAJ7GIGBlBGYEIArAGkZ1gubXV6uJ6OD7nH7A8HBs9xCIpKo3VG3bGnPGg0i0D5jexTcELaK6rbsIYoBGtR6sxbtAGXLnE7ynWYxLVtM6_aH7BA_cnU37K9Wkcl7eWO-Zu73mP3zUOUw6qRcgmQ0NY0o74tZq3ZrLX3dHvY3KgRXEj-VJ91BD8wAHzMFzTvcHuBH1R3h8AWkp7bvveaasJG9ZetmfqVJKcR0qU6ZgaesYtswJJ4h8kh8GkcGroBcQhMemYQY2v5OAAHCh5HyjCuCEeBMYkVRfpUTBvgmHATh0UhjZysxbisXCoLiHqBoMD2YG6vqhpqAwqa6AJmCFCYZCGNo1Fis8cCdBg2p8EJVh4dIPg_mmqhOG-bT-IEwS_MwERsaYTisckBa-B-uSqFC6FtEcSwMnZfrWOxTnecwLnGe5yiqCKoX1LStz3AFDkcc54iuSZHlVBZdRBaYEJcQ2aS8RM_GxfEwTXDhtn2blHGBexEIKeaxC6fprHZLwG5bjuvBgAAvgAukAA|Modern Artist]]
++++
==== Aufgaben F ====
**Vorwissen:**
* [[gf_informatik:funktionen|Funktionen]]
* Bis und mit Beispiel 4 "Funktion mit Parameter und Rückgabewert"
Bei diesen Aufgaben geht es um folgendes:
* Funktionen mit Rückgabewert verstehen und anwenden.
* Lernen, wann man eine Funktion (k)einen Rückgabewert haben sollte.
=== Aufgabe F1 ===
Definiere eine Funktion mit einem Argument `volume_cube(x)`, die das Volumen eines Würfels mit Seitenlänge $x$ (in cm) berechnet und zurückgibt (also NICHT printed). Speichere das Resultat in einer Variablen und gebe es dann aus.
Welches Volumen hat ein Würfel mit Seitenlänge 13 cm?
=== Aufgabe F2 ===
**Satz von Pythagoras:** Schreibe eine Funktion `pythagoras(a,b)`, mit der du die Hypotenuse eines rechtwinkligen Dreiecks mit Katheten $a$ und $b$ berechnen kannst. Das Resultat soll *zurückgegeben* werden.
//Tipp:// Die Wurzel einer Zahl ziehst du mit `sqrt(x)`, dazu musst du aber zuerst das math-Modul importieren: `import math`.
//Kontrolle:// Für die Katheten 3 und 4 ist die Hypothenuse 5. Die Codezeile `print(pythagoras(3,4))` soll dann also `5.0` ausgeben.
=== Aufgabe F3 ===
Das Volumen einer Kugel mit Radius $R$ ist: $$V = \frac{4\pi}{3}\cdot R^3$$
Definiere eine Funktion `volume_sphere(...)`, der man als Argument den Radius übergibt und die dann das Volumen zurückgibt. Die Kreiszahl Pi ($\pi$) kannst du mit `math.pi` aufrufen, dazu muss aber auch wieder zuerst das math-Modul importiert werden (`import math`).
=== Aufgabe F4 ===
Schreibe eine Funktion `grade(points)`, die dir die Note (_en_. grade) für eine gegebene Punktzahl berechnet und zurückgibt. Lege die Punktzahl, die für die Note $6$ notwendig ist in einer Konstanten (wie Variable, aber alles Grossbuchstaben) fest. Die Formel geht wie folgt:
$$\text{Note} = \frac{5 \cdot \text{(erreichte Punkte)}}{\text{Punktzahl für Note 6}} + 1$$
Beachte:
* Um die Noten schön zu runden, kannst du die //vordefinierte Funktion// `round` verwenden: `round(3.14159,2)` rundet dir die Zahl $3.14159$ auf zwei Nachkommastellen, man erhält also $3.14$.
* Erreicht man mehr Punkte als notwendig für Note 6, soll man trotzdem die Note 6 erhalten.
=== Aufgabe F5 ===
Die **Fakultät** ist eine Funktion, welche jeder ganzen natürlichen Zahl das Produkt aller natürlichen Zahlen (ohne Null) kleiner und gleich dieser Zahl zuordnet. Sie wird mit einem Ausrufezeichen geschrieben. Als Beispiel: $5!=1 \cdot 2 \cdot 3 \cdot 4 \cdot 5 =120$.
Schreibe eine Funktion `factorial(...)`, der als Argument eine ganze Zahl übergeben wird und die dir dann die Fakultät dieser Zahl zurückgibt.
**optionale Challenge für absolute Freaks**: Kannst du die Fakultät ganz ohne Schleife berechnen? Dann hast du das Prinzip der *Rekursion* (Selbst-Aufruf) entdeckt!
=== Aufgabe F6 (optional) ===
**Mitternachtsformel:** Eine quadratische Funktion kann immer in die Form $$ax^2 + bx + c = 0$$ gebracht werden. Die Lösung ist gegeben durch:
$$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$$
Schreibe eine Funktion `mitternachtsformel(...)`, die die drei Werte für $a,b,c$ entgegennimmt und die Lösung(en) zurück gibt. Beachte, dass es drei Fälle gibt:
* keine Lösung: gib `None` zurück, dies ist der Fall, wenn der Term in der Wurzel negativ ist
* eine Lösung, dies ist der Fall, wenn der Term in der Wurzel genau 0 ist
* zwei Lösungen: gib Liste mit den beiden Werten zurück
Tipp: Verwende die Diskriminante, um den richtigen Fall zu ermitteln.
Kontrolle: Die quadratische Gleichung ...
* $3 x^2 - 6 x - 5 = 0$ hat die zwei Lösungen: $-0.632993$ und $2.63299$
* $x^2 - 4 x + 4 = 0$ hat eine Lösung: $2$
* $x^2 + 2 x + 7 = 0$ hat keine Lösung
++++Lösungen Aufgaben F|
==== Aufgaben F ====
=== Aufgabe F1 ===
def volume_cube(x):
return x**3
v = volume_cube(13)
print(v)
=== Aufgabe F2 ===
def pythagoras(a,b):
return sqrt(a*a + b*b)
print(pythagoras(3,4))
=== Aufgabe F3 ===
import math
def volume_sphere(r):
return 4*math.pi/3 * r**3
print(volume_sphere(3))
=== Aufgabe F4 ===
def grade(points,points_6):
gr = 5*points/points_6 + 1
if gr > 6:
gr = 6.0
return round(gr,1)
print(grade(23,51))
=== Aufgabe F5 ===
def factorial(n):
product = 1
i = 1
while i <= n:
product = product * i
i = i + 1
return product
print(factorial(5))
=== Aufgabe F6 ===
def mitternachtsformel(a,b,c):
d = b*b - 4*a*c
if d < 0:
return None
elif d == 0:
return -b / (2*a)
else:
r = -b / (2*a)
return [(-b - sqrt(d)) / (2*a), (-b + sqrt(d)) / (2*a)]
print(mitternachtsformel(3,-6,-5)) # 2 Loesungen
print(mitternachtsformel(1,-4,4)) # 1 Loesung
print(mitternachtsformel(1,2,7)) # keine Loesung
++++