Python Decorators: Was sie sind, wie sie funktionieren und wozu sie dienen

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

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 = []                

Blogs

Buchempfehlungen