lehrkraefte:snr:informatik:glf22:python:funktionen

Funktionen

… oder: Wie man grössere Programme übersichtlich gestaltet.

(teilweise Vorschau auf die Videos)

Das Aufteilen eines grösseren Vorhabens in Teilvorhaben, die sogenannten Module, nennt man Modularisierung, auch modularen Entwurf oder Baukastenprinzip. Dadurch ist es leichter, die Übersicht über das gesamte Vorhaben zu behalten.

Beispiel: Beim Bau eines Hauses übernehmen verschiedene Handwerker als Spezialisten diverse Aufgaben.

In der Informatik wird dies oft durch Funktionen bewerkstelligt. Funktionen sind “Miniprogramme” oder “Unterprogramme” und erledigen eine gewisse Teilaufgabe (sie sind die “Spezialisten”).

Wir haben schon viele Funktionen kennengelernt und verwendet, z. B. print, input, forward, right, penup, setcolor, random.random.

Funktionen werden aufgerufen (Funktionsaufruf), indem man den jeweiligen Funktionsnamen angibt und danach in runden Klammern die benötigten Argumente (= Übergabewerte) angibt (manchmal wird auch gar kein Argument benötigt). Als Argumente sind integers, strings, Booleans etc. erlaubt.

Die runden Klammern sind beim Funktionsaufreu stets hinzuschreiben, auch wenn keine Argumente übergeben werden.

Beispiele:

  • pencolor(“red”) ist ein Aufruf der Funktion pencolor mit “red” als Argument.
  • penup() ist ein Aufruf der Funktion penup; diese Funktion nimmt keine Argumente entgegen.

Funktionen haben einerseits den Zweck, sonst mehrfach auftauchenden Code zu bündeln; andererseits erlauben sie es, Programme sinnvoll zu strukturieren und so lesbarer zu machen (vgl. die Videos).

Nun wirst du lernen, wie du selbst Funktionen definieren kannst!

Schau dir das folgende Video zu Funktionen an und löse die darin enthaltenen drei Aufgaben!

Video "Funktionen mit Parametern selbst definieren (teils mit Turtle)"


Endzustand der Programme aus dem Video (mit kleinen sprachlichen Verbesserungen):

Programm mit Funktionen zur Begrüssung

Programm mit Funktionen zur Begrüssung

funktionen-begruessung.py
def begruessung():
    print("Hallo!")
    print("Ich bin eine Funktion.")
 
def saluto(s):
    print("Buongiorno " + s + "!")
 
def salutation(name, sprache):
    if sprache == 1:
        print("Bonjour " + name + " !")
    else:
        print("Buongiorno " + name + "!")
 
begruessung()
 
saluto("Pinocchio")
saluto("Papagena")
 
salutation("Pinocchio", 2)
salutation("Jacques", 1)

Programm mit Funktionen zum Zeichnen mit der Turtle

Programm mit Funktionen zum Zeichnen mit der Turtle

funktionen-turtle.py
from turtle import *
 
def dreieck():
    for index in range(3):
        forward(100)
        left(120)
 
def triangolo(a):
    for index in range(3):
        forward(a)
        left(120)
 
def vieleck(a, n):
    for index in range(n):
        forward(a)
        left(360/n)
 
dreieck()
 
triangolo(123)
triangolo(200)
 
vieleck(77, 5)
vieleck(27, 11)
 
exitonclick()

Schau dir das folgende Video zu Funktionen an und löse die darin enthaltenen Aufgaben!

Video "Funktionen mit Rückgabewert"

Endzustand des Programms aus dem Video

Endzustand des Programms aus dem Video

funktionen-mit-rueckgabewerten.py
def f(x):
    return x ** 2 + 42 * x - 7
 
def zweihoch(n):
    return 2 ** n
 
def ist_teiler_von(t, z):
    return z % t == 0
 
def hoch(basis, exponent):
    return basis ** exponent
 
def summe_zweierpotenzen(n):
    summe = 0
    for index in range(n + 1):
        summe = summe + zweihoch(index)
    return summe 
 
def summe_quadratzahlen(n):
    summe = 0
    for index in range(n + 1):
        summe = summe + index ** 2
    return summe 
 
print(summe_quadratzahlen(5))
print(summe_zweierpotenzen(4))
print(hoch(3, 6))
print(hoch(2, 10))
print(ist_teiler_von(7, 42))
print(ist_teiler_von(5, 42))
print(ist_teiler_von(13, 91))
print(f(2))
print(f(11))
print(zweihoch(10))
print(zweihoch(8))

Eine Funktionsdefinition sieht in Python wie folgt aus:

def <Name der Funktion>(<keiner, einer oder mehrere durch Kommas getrennte Parameter>):
    # Hier steht, 
    # um vier Leerschläge eingerückt, 
    # was die Funktion tut.
    #
    # Falls ein Rückgabewert zurückgegeben werden soll:
    return <Ausdruck, der den Rückgabewert berechnet>

In Worten:

  • Die Funktionsdefinition wird mit einer Kopfzeile eingeleitet:
    • Sie beginnt mit dem Schlüsselwort def (für define).
    • Danach kommt der Name der Funktion, der im Wesentlichen frei gewählt werden kann.
    • Danach kommt ein Paar von Klammern, zwischen denen nichts steht oder ein Parameter (Name frei wählbar) oder mehrere durch Kommas getrennte Parameter.
    • Danach kommt ein Doppelpunkt :.
  • Nun folgt in den nächsten Zeilen eingerückt der eigentliche Code der Funktion (“body of the function”).
  • Optional, wenn ein Rückgabewert zurückgeliefert werden soll1): Verwende das Schlüsselwort return und schreibe dahinter den Ausdruck für den Rückgabewert.

Die Syntax ist also ähnlich wie bei for- oder while-Schleifen und if-Statments: Eine Art Kopfzeile mit Doppelpunkt am Ende, danach eingerückt der eigentliche Code: Dieser wird bei jedem Funktionsaufruf ausgeführt.

Öffne eine neues Python-Programm.

(1) Schreibe eine Funktion2) ist_prim(x), die entscheidet, ob der Parameterx eine Primzahl ist, und dementsprechend True oder False zurückgibt.

Hinweis

Hinweis

Initialisiere am Anfang der Funktionsdefinition eine (Hilfs-)Variable teiler_gefunden = False. Gehe dann alle möglichen Teiler von x durch und setze diese Hilfsvariable auf True, sobald du einen Teiler von x gefunden hast. (Denke an das “Divisionszeichen” %, mit dessen Hilfe man leicht herausfindet, ob eine Zahl eine andere teilt.)


(2) Nutze deine Funktion ist_prim, um eine Liste aller Primzahlen bis n = 10000 auszugeben.

Hinweis: Damit nicht jede Primzahl in einer neuen Zeile steht: Der Befehl print(p, end = “, ”) gibt den Wert der Variablen p aus, danach ein Komma gefolgt von einem Leerschlag, und geht danach nicht in die nächste Zeile.

Bemerkung: Diese Methode, eine Liste von Primzahlen, ist nicht besonders effizient. Schneller geht es etwa mit dem Sieb des Eratosthenes.

Ziel der Aufgabe ist, den kreisförmigen Mäander effizient zu zeichnen.

Da die rote Figur mehrfach vorkommt, ist es sinnvoll, diese Figur von einer Funktion zeichnen zu lassen.

  • (1) Definiere eine Funktion ornament(a): Sie soll den roten Streckenzug zeichnen, wobei das “kürzeste” Teilstück a Pixel lang ist. Die beiden anderen Teilstücke sind dann 2 * a und 3 * a Pixel lang. Der Streckenzug soll links oben beginnend gezeichnet werden mit Blickrichtung der Turtle nach rechts; am Ende soll sie wieder nach rechts schauen).

Hinweis: Die Bilder wurden mit a = 20 erzeugt.

  • (2) Verwende deine Funktion und eine for-Schleife, um den folgenden Mäander zu zeichnen (alles soll einfarbig sein). Passe die Stiftdicke geeignet an.

  • (3) Ändere dein Programm so, dass der obige kreisförmige Mäander entsteht, der aus n = 23 Einzelmustern besteht (wieder alles einfarbig). Zum anfänglichen Positionieren der Turtle könnte die folgende Infobox nützlich sein.

Bonusaufgaben (bitte ausklappen)

Bonusaufgaben (bitte ausklappen)

Zeichne den folgenden rechteckigen Mänder mit Hilfe einer zusätzlichen Funktion eckbewegung(), die den orangen Teil des Musters zeichnet und viermal aufgerufen wird.

Zeichne ähnliche Muster! Zur Inspiration:

Die wichtigsten Zustandsparameter der Turtle sind ihre Position und ihre Blickrichtung (weniger wichtig sind Farbe und Stiftdicke etc.).

  • Ihre Position wird durch $x$- und $y$-Koordinate angegeben.
  • Ihre Blickrichtung wird durch einen Winkel in Grad angegeben: $0^\circ$: nach rechts; $90^\circ$: nach oben, $180^\circ$: nach links etc.

Das zugrunde liegende Koordinatensystem liegt zentriert im Standard-Turtle-Fenster: Sichtbar sind alle Punkte mit

  • x-Koordinaten zwischen -473 und +473 und
  • y-Koordinaten zwischen -398 und +398. 3)

Man kann die Turtle direkt in einen gewissen Zustand versetzen:

  • setposition(-100, 50) bewegt die Turtle auf den Punkt $(-100, 50)$. (Kürzer hat setpos(-100, 50) denselben Effekt.)
  • setheading(45) dreht man die Turtle so, dass ihre Blickrichtung zur positiven $x$-Achse einen Winkel von $45^\circ$ bildet bildet (in mathematisch positivem Drehsinn, also dem Gegenuhrzeigersinn), die Turtle schaut also nach rechts oben. (Kürzer hat seth(45) denselben Effekt.)
  • home() bewegt die Turtle in die Start-Position.

Alles vor dem roten Kasten sollte bekannt sein auf der Seite https://www.w3schools.com/python/python_functions.asp.

Exercises dazu (die ersten vier Fragen solltest du beantworten können): https://www.w3schools.com/python/exercise.asp?filename=exercise_functions1

Zum besseren Verständnis ist es sinnvoll, Funktionen in vier Arten einzuteilen, je nachdem, ob sie

  • Parameter besitzen oder nicht (also Argumente beim Funktionsaufruf angegeben werden müssen oder nicht);
  • einen Rückgabewert zurückgeben oder nicht.

In der folgenden Tabelle ist für jeder dieser vier Arten ein Beispiel angegeben und darunter ein Aufruf der Funktion.

Funktionen ohne Parameter mit Parameter(n)
ohne Rückgabewert penup pensize
penup() pensize(10)
mit Rückgabewert random.random input
random.random() input(“Wie heisst du?”)

Grob gesagt kann man Aufrufe und Definitionen von Funktionen daran erkennen, dass nach ihnen ein Paar runder Klammern (mit oder ohne Argumente bzw. Parameter dazwischen) auftaucht!

Beachte: Sogenannte Schlüsselworte wie if, else, for, while, def etc. sind keine Funktionen. Sie werden verwendet, um den Ablauf von Python-Programmen zu steuern.

Bisher nicht in diesem Kurs erklärt: Variablen haben in Python Geltungsbereiche, vgl. https://www.w3schools.com/python/python_scope.asp.

Dies erlaubt, denselben Variablennamen mehrfach zu verwenden (etwa eine Variable namens x im “Hauptprogramm” und eine Variable (oder einen Parameter) namens x in einer Funktion), ohne dass dies zu Konfliken führt.

Wenn man als Programmieranfänger auf Nummer sicher gehen will, verwende man jeden Variablennamen nur einmal.

Ergänze das folgende Programm um die Definition zweier Funktionen (um so das obige Bild zu zeichnen):

  • Eine Funktion spirale mit vier Parametern: Der Funktionsaufruf spirale(80, 1, 2, 61) soll eine Spirale aus 80 Segmenten mit Anfangslänge 1, Veränderung 2 und Abbiegewinkel 61 zeichnen (also die leicht verdrehte hexagonale Spirale im obigen Screenshot).
  • Eine Funktion bewege_unsichtbar mit zwei Parametern: Der Funktionsaufruf bewege_unsichtbar(-200, 200) soll die Turtle ohne zu zeichnen auf die Position (-200, 200) bewegen.
vorlage-funktionen-spirale-und-bewege.py
from turtle import * 
 
def spirale(n, a, veraenderung, winkel):
#
# Ergänze hier den "Funktionsrumpf" der Funktion "spirale",
# also den Code, der eine Spirale abhängig
# von den obigen Parametern zeichnet.
#
 
# Ergänze hier die Definition der Funktion "bewege_unsichtbar".
# Hinweis: Verwende die Funktion "setpos(x,y)".
 
speed(0)
 
bewege_unsichtbar(200, 200)
spirale(40, 10, 5, 90)
 
bewege_unsichtbar(-200, 200)
spirale(30, 10, 5, 360/6)
 
bewege_unsichtbar(-200, -200)
spirale(80, 1, 2, 61)
 
bewege_unsichtbar(200, -200)
spirale(150, 1, 0.3, 360/20)
 
exitonclick()

Lösungsvorschlag

Lösungsvorschlag

funktionen-spirale-und-bewege.py
from turtle import * 
 
def spirale(n, a, veraenderung, winkel):
    for index in range(n):
        forward(a + index * veraenderung)
        left(winkel)
 
def bewege_unsichtbar(x, y):
    penup()
    setpos(x, y)
    pendown()
 
speed(0)
 
bewege_unsichtbar(200, 200)
spirale(40, 10, 5, 90)
 
bewege_unsichtbar(-200, 200)
spirale(30, 10, 5, 360/6)
 
bewege_unsichtbar(-200, -200)
spirale(80, 1, 2, 61)
 
bewege_unsichtbar(200, -200)
spirale(150, 1, 0.3, 360/20)
 
exitonclick()

1)
so, wie man das erwartet, wenn man an den Funktionsbegriff in der Mathematik denkt
2)
Eigentlich heisst die Funktion nur ist_prim (und nicht ist_prim(x)).
3)
jedenfalls auf meinem Laptop; wenn ich die Dokumentation richtig verstehe, nimmt das Standard-Turtle-Fenster 50 % der Bildschirmbreite und 75 % der Bildschirmhöhe ein
  • lehrkraefte/snr/informatik/glf22/python/funktionen.txt
  • Last modified: 2022/11/29 12:10
  • by Olaf Schnürer