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.fixturebeim 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)- Denkanstoß
innen muss das Ergebnis der echten Funktion zurückgeben –
returnfunktion(*args) - Welcher Befehl hilft?
Erhöhe in innen den Zähler mit
innen.aufrufe+=1 - Lückencode – ergänze die ___
def zaehlen(funktion): def innen(*args): innen.aufrufe += ___ return ___ 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🔒 Erst nach allen Hinweisen oder 2 Prüf-Versuchen
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)