Was sind Decorators in Python?
Wenn Sie länger als eine Woche mit Python arbeiten, haben Sie bestimmt schon das @-Symbol über einer Funktion gesehen. Das ist ein Decorator — ein mächtiges und dennoch einfach verständliches Programmierwerkzeug.
Decorators in Python ermöglichen es, eine Funktion in eine andere zu "verpacken". Sie verändern oder erweitern das Verhalten einer Funktion, ohne deren ursprünglichen Code zu ändern. Decorators werden überall eingesetzt: in Flask, Django, FastAPI, pytest und sogar in der Python-Standardbibliothek.
Wie Decorators funktionieren
Grundlagen der Decorators
Ein Decorator ist eine Funktion, die eine andere Funktion entgegennimmt und eine neue oder modifizierte Version zurückgibt.
def decorator(func):
def wrapper():
print("Vor dem Aufruf")
func()
print("Nach dem Aufruf")
return wrapper
@decorator
def say_hello():
print("Hallo!")
say_hello()
Ausgabe:
Vor dem Aufruf
Hallo!
Nach dem Aufruf
Das @decorator ist syntaktischer Zucker für:
say_hello = decorator(say_hello)
Interner Aufbau von Decorators
Um Decorators in Python zu verstehen, müssen Sie diese Schlüsselkonzepte kennen:
- In Python sind Funktionen Objekte erster Klasse
- Funktionen können als Argumente an andere Funktionen übergeben werden
- Innerhalb von Funktionen können weitere Funktionen definiert werden
- Es gibt den Mechanismus der Closures
Universelles Decorator-Muster
Das minimale Decorator-Muster sieht so aus:
def decorator(func):
def wrapper(*args, **kwargs):
# Aktionen vor der Funktionsausführung
result = func(*args, **kwargs)
# Aktionen nach der Funktionsausführung
return result
return wrapper
Praktische Beispiele für Decorators
Decorator zur Messung der Ausführungszeit
import time
def timing(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
execution_time = time.time() - start
print(f"{func.__name__} dauerte {execution_time:.4f} Sekunden")
return result
return wrapper
@timing
def slow_func():
time.sleep(1)
return "Vorgang abgeschlossen"
slow_func()
Dieser Decorator ist nützlich für das Profiling der Performance von Funktionen und die Code-Optimierung.
Decorator zur Autorisierungsprüfung
def require_admin(func):
def wrapper(user, *args, **kwargs):
if user != "admin":
raise PermissionError("Zugriff verweigert")
return func(user, *args, **kwargs)
return wrapper
@require_admin
def delete_database(user):
print("Datenbank gelöscht!")
return True
delete_database("admin") # Erfolgreiche Ausführung
Ein solcher Decorator erhöht die Sicherheit einer Anwendung, indem er den Zugriff auf kritische Funktionen kontrolliert.
Decorator für Logging
import logging
from functools import wraps
def log_calls(func):
@wraps(func)
def wrapper(*args, **kwargs):
logging.info(f"Aufruf der Funktion {func.__name__} mit Argumenten {args}, {kwargs}")
try:
result = func(*args, **kwargs)
logging.info(f"Funktion {func.__name__} erfolgreich ausgeführt")
return result
except Exception as e:
logging.error(f"Fehler in Funktion {func.__name__}: {e}")
raise
return wrapper
Decorators mit Argumenten
Erstellung einer Decorator-Factory
Wenn ein Decorator Parameter entgegennehmen soll, wird eine Decorator-Factory erstellt:
def repeat(n):
def decorator(func):
def wrapper(*args, **kwargs):
results = []