Zum Inhalt springen
BetaEN
Lektion 32 von 35Python

Python · Lektion 32 · 30 Minuten

Decorators

Das lernst du

  • Funktionen als Werte weitergeben
  • Einen eigenen Decorator schreiben
  • Mit @ eine Funktion erweitern

Funktionen sind auch nur Werte

In Python kannst du Funktionen wie Zahlen oder Texte in Variablen speichern und an andere Funktionen übergeben:

def laut(text):
    return text.upper() + "!"

def zweimal(funktion, wert):
    return funktion(funktion(wert))

sag = laut
print(sag("hallo"))
print(zweimal(laut, "hey"))

Eine Funktion, die Funktionen verpackt

Ein Decorator bekommt eine Funktion und gibt eine neue, erweiterte Funktion zurück. Hier misst einer, wie lange eine Funktion braucht:

import time

def stoppuhr(funktion):
    def innen(*args):
        start = time.perf_counter()
        ergebnis = funktion(*args)
        dauer = time.perf_counter() - start
        print(f"{funktion.__name__} brauchte {dauer:.4f} s")
        return ergebnis
    return innen

def summe_bis(n):
    return sum(range(n))

summe_bis = stoppuhr(summe_bis)
print(summe_bis(1_000_000))

*args heißt: „alle Werte, die übergeben werden, egal wie viele“.

Die @-Schreibweise

summe_bis = stoppuhr(summe_bis) ist etwas umständlich. Deshalb gibt es die Abkürzung mit @ direkt über der Funktion – das ist genau dasselbe:

def schreien(funktion):
    def innen(*args):
        return funktion(*args).upper()
    return innen

@schreien
def begruessen(name):
    return f"hallo {name}"

print(begruessen("codelix"))

Merke: Decorators siehst du in großen Projekten überall – zum Beispiel @app.route("/") in Web-Frameworks oder @pytest.fixture beim Testen.

Kurz-Check

Bevor es an die Aufgabe geht: Was gibt dieses Programm aus? Tipp deine Vermutung ein – Python rechnet danach nach.

def laut(funktion):
    def huelle():
        return funktion().upper() + "!"
    return huelle


@laut
def gruss():
    return "hallo"


print(gruss())

Deine Aufgabe

Jetzt bist du dran

Schreib einen Decorator zaehlen, der mitzählt, wie oft eine Funktion aufgerufen wird. Die Anzahl soll in der Eigenschaft aufrufe der neuen Funktion stehen. Dekoriere damit gruss und rufe sie dreimal auf.

def zaehlen(funktion):
    def innen(*args):
        # zähle mit und rufe die echte Funktion auf
        pass
    innen.aufrufe = 0
    return innen


@zaehlen
def gruss(name):
    return f"Hallo {name}"


print(gruss("Mia"))
print(gruss("Ben"))
print(gruss("Lea"))
print(gruss.aufrufe)

Ohne Hinweise gelöst gibt es einen ⭐ auf deiner Fortschrittsseite.

Lösung anzeigen

Versuch es erst selbst – aus Fehlern lernt man am meisten. Hier ist eine mögliche Lösung:

def zaehlen(funktion):
    def innen(*args):
        innen.aufrufe += 1
        return funktion(*args)
    innen.aufrufe = 0
    return innen


@zaehlen
def gruss(name):
    return f"Hallo {name}"


print(gruss("Mia"))
print(gruss("Ben"))
print(gruss("Lea"))
print(gruss.aufrufe)