4 – Funktionen

Einführung in Python und PsychoPy

Autor

Clemens Brunner

Veröffentlicht

23. Oktober 2025

Allgemeines

Funktionen kann man sich wie “Mini-Programme” bzw. “Mini-Scripts” vorstellen. Sie gruppieren mehrere Anweisungen zu einem zusammengehörigen Block. Eine Funktion in Python ist durchaus mit einer mathematischen Funktion vergleichbar, wie zum Beispiel der Quadratfunktion \(f(x) = x^2\). Diese mathematische Funktion \(f\) berechnet aus einem gegebenen Wert \(x\) einen neuen Wert \(x^2\). Diese Funktion kann man dann mit konkreten Werten für \(x\) verwenden, um die entsprechenden Ergebnisse zu erhalten, z.B. \(f(3) = 9\) oder \(f(5) = 25\).

Auch in Python hat eine Funktion eine klar definierte Aufgabe. Hier dienen Funktionen unter anderem dazu, Programmcode zu strukturieren (was die Lesbarkeit erhöht) und wiederverwendbar zu machen (wiederverwendbar bedeutet, dass man eine Funktion beliebig oft verwenden kann). Funktionen machen Programme in der Regel auch kürzer, weil wiederholt auszuführender Code in Funktionen ausgelagert werden kann. Sollten einmal Änderungen notwendig sein, muss man diese nur an einer Stelle innerhalb der Funktion vornehmen. Funktionen lassen sich außerdem auch in anderen Programmen wiederverwenden.

Hinweis

Einige Funktionen wie print und type haben wir bereits in den vorigen Einheiten kennengelernt und verwendet.

Funktionen aufrufen

Eine Funktion aufrufen bedeutet, dass der in ihr enthaltene Code (also das “Mini-Programm”) ausgeführt wird – die Funktion verrichtet also ihre Arbeit.

In Python ruft man eine Funktion mit ihrem Namen gefolgt von einem Paar runder Klammern auf. Innerhalb der Klammern werden die Argumente für die Funktion übergeben (falls notwendig). Mit Argumenten übergibt man der Funktion Werte, welche diese für die Ausführung benötigt. Beispielsweise benötigt die Funktion type ein Argument, denn sonst kann sie ihre Aufgabe nicht erfüllen – nämlich den Typ des übergebenen Arguments zu bestimmen. Gleichermaßen braucht auch die Funktion math.sqrt aus dem math-Modul ein Argument, damit diese die Wurzel der übergebenen Zahl berechnen kann.

Hier sind drei Beispiele für Aufrufe von bereits bekannten Funktionen mit jeweils einem Argument:

print("Hello")
Hello
type("Hello")
str
import math
math.sqrt(16)
4.0

Es gibt aber auch Funktionen, die man ohne Argument aufrufen kann (der folgende Funktionsaufruf bewirkt eine Ausgabe einer Leerzeile am Bildschirm):

print()

Wie viele Argumente eine Funktion tatsächlich benötigt, hängt ganz alleine von der jeweiligen Funktion ab (dies ist in ihrer Dokumentation nachzulesen).

Wichtig

Lässt man die Klammern weg, wird die Funktion nicht aufgerufen – es wird dann lediglich der Wert des Namens (also das Funktionsobjekt) angezeigt, wenn man Python im interaktiven Modus verwendet.

print
<function print(*args, sep=' ', end='\n', file=None, flush=False)>

Dabei handelt es sich um einen Namen, welcher auf ein Funktionsobjekt verweist:

type(print)
builtin_function_or_method

Das Konzept von Namen in Python haben wir bereits in der letzten Einheit kennengelernt. Es ist unerheblich, auf welches Objekt ein Name verweist, dies kann eine Ganzzahl, eine Funktion, oder jedes beliebige andere Objekt sein. So können wir z.B. auch den Namen f erstellen, welcher auf die Funktion print verweist:

f = print

Nun hat die Funktion zwei Namen, nämlich print und f:

f("Hello via f")
Hello via f

Funktionen definieren

Wir sind glücklicherweise nicht auf bereits existierende Funktionen beschränkt, sondern können selbst unsere eigenen Funktionen schreiben. In Python wird eine Funktion wie folgt definiert (die Zeilen in spitzen Klammern sind Platzhalter und müssen durch konkrete Befehle ersetzt werden):

def function_name(parameter1, parameter2, ...):
    <do something>
    <...>
    <optionally return something>

Eine Funktionsdefinition beginnt immer mit dem Schlüsselwort def. Danach folgt der (frei wählbare) Funktionsname (aber auch hier muss man sich an die Regeln für gültige Namen halten). Die PEP8-Konvention empfiehlt außerdem, dass Funktionsnamen keine Großbuchstaben enthalten sollten. Falls der Name aus mehreren Wörtern bestehen soll, sollten Unterstrichen zur Trennung verwendet werden, z.B.:

def test_function

Nach dem Funktionsnamen folgt ein Paar runder Klammern. Innerhalb dieser können von der Funktion benötigte Parameter aufgelistet werden (mehrere Parameter werden durch Kommas voneinander getrennt). Parameter sind Platzhalter, welche beim Ausführen der Funktion mit spezifischen Werten ersetzt werden. Diese spezifischen Werte (auch Argumente genannt) werden beim Aufruf übergeben. Es gibt aber auch Funktionen, die keine Parameter haben – die beiden runden Klammern müssen aber trotzdem immer vorhanden sein:

def test_function()  # ohne Parameter

Falls eine Funktion zwei Parameter haben soll, würde man dies wie folgt anschreiben:

def test_function(n, v)  # zwei Parameter namens n und v

Unabhängig von der Anzahl der Parameter schließt ein Doppelpunkt den sogenannten Funktionskopf ab:

def test_function(n, v):

Nun folgt der Code, welcher von der Funktion ausgeführt wird, wenn diese aufgerufen wird – dieser Code muss um eine Ebene eingerückt werden (also normalerweise vier Leerzeichen). Man spricht hier vom sogenannten Funktionskörper. Im Funktionskörper kann man insbesondere alle Parameter wie normale Namen verwenden – diese sind nur innerhalb der Funktion vorhanden und erhalten dann die konkreten Werte der Argumente, welche beim Funktionsaufruf übergeben wurden.

Wichtig

Eine Funktion kann Parameter haben, welche bei der Definition aufgelistet werden müssen. Wenn man die Funktion aufruft, muss man für alle Parameter konkrete Werte übergeben – diese konkreten Werte nennt man Argumente.

Das folgende Beispiel definiert eine Funktion namens test_function, welche aus zwei Zeilen Code im Funktionskörper besteht:

def test_function():
    s = "Hello world!"
    print(s)

Man beachte, dass die Funktion hier lediglich definiert wurde, d.h. sie wurde noch nicht ausgeführt. Sie ist aber dem Python-Interpreter ab jetzt bekannt (d.h. es existiert ein Name test_function, welcher auf ein Funktionsobjekt verweist):

test_function
<function __main__.test_function()>
type(test_function)
function

Aufgerufen kann unsere Funktion nun wie folgt werden (die runden Klammern sind essentiell):

test_function()
Hello world!

Wir können eine bereits definierte Funktion beliebig oft aufrufen.

test_function()
Hello world!

Im Fall einer Funktion mit Parametern würden die Definition und der Aufruf z.B. so aussehen (wir haben den verwendeten if-Befehl noch nicht besprochen, es ist aber nicht wichtig, dass Sie verstehen, was diese Funktion genau macht):

def test_function_2(n, v):  # Definition, zwei Parameter
    if v:
        print(n)
test_function_2("Hello world!", True)  # Aufruf mit zwei konkreten Argumenten
Hello world!
test_function_2("Hi!", False)  # weiterer Aufruf mit anderen Argumenten

Übergibt man beim Aufruf dieser Funktion nicht genau die erwartete Anzahl an Argumenten, bekommt man einen Fehler:

test_function_2()  # zwei Argumente erwartet, aber keine übergeben!
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[17], line 1
----> 1 test_function_2()  # zwei Argumente erwartet, aber keine übergeben!

TypeError: test_function_2() missing 2 required positional arguments: 'n' and 'v'
Wichtig

Alle in der Funktionsdefinition definierten Parameter müssen beim Aufrufen der Funktion mit konkreten Argumenten befüllt werden!

Tipp

Es ist üblich, gleich in der ersten Zeile des Funktionskörpers eine kurze Beschreibung der Funktion in einem sogenannten Docstring anzugeben (dieser kann sich auch über mehr als eine Zeile erstrecken). Ein Docstring wird von jeweils drei Anführungszeichen """ umschlossen. Das Vorhandensein eines Docstrings ändert nichts an der Funktionsweise, dient aber der Dokumentation und gehört zum guten Coding-Stil dazu, wie folgendes Beispiel demonstriert:

def test_function():
    """Print hello world."""
    s = "Hello world!"
    print(s)

Ein solcher Docstring ist übrigens kein Kommentar! Verwenden Sie für Kommentare also weiterhin das #-Zeichen!

Rückgabewerte

Funktionen können Werte (Ergebnisse) zurückgeben. In beiden soeben definierten Funktionen test_function und test_function_2 wird allerdings kein Wert explizit zurückgegeben (d.h. die Funktionen führen nur Code aus und geben implizit None zurück, der spezielle Wert für “nichts” in Python). Diese beiden Funktionen können also nicht auf einen Wert reduziert werden, wenn man sie aufruft – sie sind also keine Ausdrücke.

Wenn eine Funktion explizit einen Wert (ein Ergebnis) zurückgeben soll, verwendet man dazu das Schlüsselwort return, gefolgt vom gewünschten Rückgabewert:

def add_one(number):
    """Increment a given number by one."""
    return number + 1

Beim Aufrufen der Funktion wird ihr Code im Funktionskörper ausgeführt, bis die Zeile mit return erreicht wird. Diese bewirkt, dass die Funktion sofort verlassen und der angegebene Wert number + 1 zurückgegeben wird (hier wird für number natürlich der als Argument übergebene konkrete Wert verwendet). Sollten also nach dem return-Befehl noch weitere Zeilen Code im Funktionskörper folgen, werden diese nicht mehr ausgeführt.

add_one(5)
6

Ein Funktionsaufruf wird also immer auf seinen Rückgabewert reduziert. Ein Aufruf einer Funktion, die einen Wert zurückgibt, ist also ein Ausdruck. Nun könnte man diesem auch einen Namen geben:

x = add_one(9)
x
10

Man kann den Wert einer Funktion (also den Rückgabewert) auch explizit mit Hilfe der print-Funktion am Bildschirm ausgeben:

print(add_one(122))
123
Tipp

Man kann überall dort, wo man einen Wert angeben kann, auch einen Ausdruck (eine beliebige Kombination aus Werten und Operatoren) einsetzen – eben auch einen Funktionsaufruf, der einen Wert zurückgibt. Dies wird als Komposition bezeichnet. Die Werte werden der Reihe nach (von innen nach außen) verarbeitet und eingesetzt, bis zum Schluss ein einziger Wert übrig bleibt:

add_one(add_one(add_one(1)))
4

Argumente

Standard-Argumente

Eine Funktion kann keine Parameter haben oder eine bestimmte Anzahl an Parametern erwarten. Wenn eine bestimmte Anzahl an Parametern im Funktionskopf definiert wird, können einzelnen Parametern Standardwerte (sogenannte Standard- oder auch Default-Argumente) zugewiesen werden. Dies bedeutet, dass die Funktion auch mit weniger Argumenten als erwartet aufgerufen werden kann, wenn für die fehlenden Argumente Standardwerte existieren.

def add(number, increment=1):  # das Standard-Argument für increment ist 1
    return number + increment

Diese Funktion kann jetzt mit zwei Argumenten oder nur mit dem ersten Argument aufgerufen werden:

add(7, 1)
8
add(7)  # hier wird das Standard-Argument 1 für increment verwendet
8
add(7, 3)
10

Schlüsselwort-Argumente

Funktionen können auch so aufgerufen werden, dass die Namen der Parameter gemeinsam mit den Argumenten in der Form kwarg=value explizit hingeschrieben werden. Man spricht dann von Schlüsselwort-Argumenten (englisch “Keyword Arguments”) (nicht zu verwechseln mit den Python-Schlüsselwörtern). D.h. die obige Funktion add kann auch so aufgerufen werden:

add(number=5)
6
add(number=5, increment=2)
7
add(increment=2, number=5)
7

Dies dient einerseits der besseren Lesbarkeit, da unmittelbar klar ist, welche Parameter welche konkreten Argumente erhalten. Andererseits kann man so die Argumente auch in beliebiger Reihenfolge übergeben.

Wenn der Argumentname nicht angegeben wird, wird die Position des Arguments bei der Zuweisung herangezogen. Man spricht in diesem Fall von positionalen Argumenten. Man kann positionale und Schlüsselwort-Argumente beim Funktionsaufruf auch mischen, aber alle positionalen Argumente müssen vor dem ersten Schlüsselwort-Argument kommen.

add(5, increment=2)
7

Zur Veranschaulichung dient folgende Funktionsdefinition:

def test(name, number, exponent=5, skip=7, text="Hello"):
    print(text, name, end=" ")
    return number**exponent - skip

Die folgenden drei Funktionsaufrufe verwenden nur positionale Argumente:

test("Python", 2)
Hello Python 
25
test("Python", 3)
Hello Python 
236
test("Test", 3, 4)
Hello Test 
74

Schlüsselwort-Argumente sind sehr praktisch, wenn man für viele Parameter deren Standard-Argumente verwenden möchte, aber z.B. für einen einzigen Parameter einen anderen Wert setzen will. Dann muss man nämlich nicht alle Argumente der Reihe nach übergeben, sondern nur jene, für die man andere Werte als die Standardwerte haben möchte:

test("Test", 2, skip=2)
Hello Test 
30

Ohne Schlüsselwort-Argumente würde derselbe Aufruf nämlich wie folgt aussehen:

test("Test", 2, 5, 2)
Hello Test 
30

Man muss also in diesem Beispiel ein zusätzliches Argument 5 (für den Parameter exponent) übergeben, wenn man positionale Argumente verwendet, obwohl man ja ohnehin den Standardwert dieses Arguments verwendet.

Hinweis

In Python gibt es auch Funktionen, die eine beliebige/variable Anzahl an Parametern besitzen. Dies bedeutet, dass bei der Funktionsdefinition festgelegt wird, dass eine beliebige Anzahl an Argumenten übergeben werden kann. Die print-Funktion ist ein Beispiel für eine solche Funktion: diese kann man mit keinem, einem, zwei, oder beliebig vielen Argumenten aufrufen:

print()
print("Hello")
print("Hello", "Python")
print("Hello", "Python", 1, 2, 3, 4)

Hello
Hello Python
Hello Python 1 2 3 4

Wir werden solche Funktionen nicht im Detail besprechen (vor allem nicht, wie man diese selbst definieren kann), aber wir werden solche Funktionen mitunter verwenden (aufrufen).

Gültigkeitsbereiche

Alles, was innerhalb einer Funktion (im Funktionskörper) definiert wird, ist nur innerhalb dieser Funktion sichtbar und zugreifbar. Man spricht von einem lokalen Gültigkeitsbereich (englisch “Scope”), welcher sich auf die Funktion und eventuelle weitere in ihr vorhandene untergeordnete Bereiche erstreckt. Gültigkeitsbereiche entsprechen in Python im Prinzip den Einrückungen.

Im folgenden Beispiel wird innerhalb der Funktion test der Name s = 15 definiert. Dieser kann innerhalb der Funktion verwendet werden.

def test():
    s = 15  # s ist nur lokal in der Funktion definiert
    print(s)

test()
15

Außerhalb dieser Funktion existiert dieses s aber nicht:

print(s)  # außerhalb der Funktion existiert s nicht
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[41], line 1
----> 1 print(s)  # außerhalb der Funktion existiert s nicht

NameError: name 's' is not defined

Umgekehrt kann man aber sehr wohl auf Namen, die außerhalb (bzw. oberhalb) eines Gültigkeitsbereichs definiert wurden, zugreifen:

s = 15  # "globales" s

def test():
    print(s)  # s aus dem globalen Scope ist zugänglich

test()
print(s)  # s existiert global
15
15

Wenn man innerhalb einer Funktion einen neuen Namen erstellt, welcher auch außerhalb existiert, dann ist nur der neue lokale Name zugänglich und der Name von außerhalb wird innerhalb der Funktion versteckt (englisch “shadowed”). Im folgenden Beispiel verweisen die beiden Namen s auf unterschiedliche Objekte:

s = 15  # globales s

def test():
    s = 12  # lokales s ändert globales s nicht, versteckt es aber in der Funktion
    print(s)

test()
print(s)
12
15

Besonders seltsam mutet folgendes Beispiel an, welches eine Fehlermeldung verursacht:

s = 15  # globales s

def test():
    print(s)  # lokales s existiert noch nicht - daher Fehler!
    s = 12  # lokales s
    print(s)

test()
print(s)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Cell In[44], line 8
      5     s = 12  # lokales s
      6     print(s)
----> 8 test()
      9 print(s)

Cell In[44], line 4, in test()
      3 def test():
----> 4     print(s)  # lokales s existiert noch nicht - daher Fehler!
      5     s = 12  # lokales s
      6     print(s)

UnboundLocalError: cannot access local variable 's' where it is not associated with a value

Die Zeile print(s) in der Funktion verursacht einen Fehler, weil Python aufgrund der folgenden Zeile bereits weiß, dass s ein lokaler Name sein wird. Daher kann print(s) auch nicht funktionieren, weil s in der ersten Zeile noch nicht existiert! Hier mischt Python also nicht zwischen globalen und lokalen Namen.

Möchte man aber tatsächlich den global definierten Namen verwenden, kann man dies mit dem Schlüsselwort global tun:

s = 15  # globales s

def test():
    global s  # Ermöglicht Zugriff auf das globale s
    print(s)
    s = 12  # ändert globales s
    print(s)

test()
print(s)
15
12
12

Prinzipiell sollte man die Deklaration global aber vermeiden und globale/lokale Scopes sauber voneinander trennen. Will man auf ein Objekt aus einem äußeren Scope zugreifen, definiert man am besten einen Parameter, damit man das gewünschte Objekt als Argument an die Funktion übergeben kann:

s = 15  # globales s

def test(s):  # Parameter s
    print(s)  # lokales s (übergebenes Argument)
    s = 12
    print(s)

print(s)
test(s)
print(s)
15
15
12
15

Will man eine lokale Variable in einem äußeren Scope weiter nutzen, gibt man den entsprechenden Wert am besten mit return zurück:

s = 15  # globales s

def test(s):
    print(s)  # lokales s (Argument)
    s = 12
    print(s)
    return s

print(s)
s = test(s)  # globales s bekommt Rückgabewert der Funktion (lokales s)
print(s)
15
15
12
12
Tipp

Das hier beschriebene Verhalten gilt auch für Parameter. Diese verhalten sich wie lokal innerhalb der Funktion definierte Namen und erhalten automatisch die Werte, die mit den entsprechenden Argumenten beim Aufruf übergeben wurden. In den letzten beiden Beispielen hatten die Funktionen jeweils einen Parameter namens s. Zufälligerweise wurden die Funktionen auch mit einem Argument namens s aufgerufen – dabei handelt es sich aber um zwei unterschiedliche Namen bzw. Objekte. Man könnte die Funktion genauso gut auch direkt mit einem Wert oder mit einem beliebigen anderen Namen aufrufen:

x = 15
test(x)  # Parameter s erhält den Wert x = 15
15
12
12

Dies sieht man insbesondere dann, wenn man Schlüsselwort-Argumente verwendet:

test(s=x)
15
12
12

Übungen

Übung 1

Suchen Sie sich aus der Liste der eingebauten Funktionen (siehe vorige Einheit) drei beliebige Funktionen aus.

  • Rufen Sie den Hilfetext zu jeder Funktion auf und lesen Sie diesen durch, um herauszufinden was die Funktion tut.
  • Rufen Sie die drei Funktionen mit geeigneten Argumenten auf.
  • Geben Sie für jede Funktion an, ob diese einen Wert zurückgibt oder nicht. Falls ein Wert zurückgegeben wird, geben Sie diesen Wert sowie dessen Typ an!

Übung 2

Schreiben Sie eine Funktion mult, welche zwei Zahlen multipliziert und deren Produkt zurückgibt. Die beiden Zahlen sollen als Argumente übergeben werden können. Rufen Sie Ihre Funktion mit ein paar Wertepaaren auf und stellen Sie sicher, dass Ihre Funktion wie gewünscht funktioniert. Die Funktion soll das Ergebnis als Wert zurückgeben, d.h. verwenden Sie innerhalb der Funktion nicht print, sondern return!

Übung 3

Schreiben Sie eine Funktion to_fahrenheit, welche einen Parameter celsius hat und diese Celsius-Temperatur in Fahrenheit umwandelt und zurückgibt. Zum Testen rufen Sie Ihre Funktion mit den Celsius-Temperaturen 0, 20, 38 und 100 auf.

Schreiben Sie außerdem eine Funktion to_celsius (mit entsprechendem Parameter fahrenheit) und wandeln Sie die vier Fahrenheit-Temperaturen, die Sie vorher beim Aufruf der Funktion to_fahrenheit erhalten haben, wieder in Celsius-Temperaturen um!

Übung 4

Nennen Sie Gründe, warum man Funktionen verwendet. Erklären Sie auch kurz den Unterschied zwischen Funktionsdefinition und Funktionsaufruf! Was ist der Unterschied zwischen Parametern und Argumenten?

Übung 5

Schreiben Sie eine Funktion namens nonsense, welche drei Parameter namens a, b und c hat. Die beiden Argumente b und c sollen optional sein und die Standardwerte 10 bzw. 13 besitzen. Die Funktion soll a**2 - b * 2 + c**2 berechnen und zurückgeben (wir setzen voraus, dass man für a, b und c immer Zahlenwerte übergibt). Rufen Sie die Funktion dann mit folgenden Argumenten auf:

  1. Ohne Argumente
  2. Mit drei positionalen Argumenten
  3. Mit zwei positionalen Argumenten
  4. Mit einem Keyword-Argument
  5. Mit zwei Keyword-Argumenten
  6. Mit zwei positionalen Argumenten und einem Keyword-Argument
  7. Mit einem positionalem und einem Keyword-Argument

Wie sehen diese Funktionsaufrufe aus? Wie lauten die Rückgabewerte? Geben Sie für jeden Aufruf die Werte aller drei Argumente an!

Hinweis

Nur der erste Funktionsaufruf (ohne Argumente) verursacht einen Fehler, alle weiteren Aufrufe sind möglich!