So erstellen und verwenden Sie Dekoratoren in Python

Erfahren Sie, wie Sie Dekoratoren in Python schreiben und anwenden. Beherrschen Sie Wrapping-Funktionen, ändern Sie Verhalten, verarbeiten Sie Argumente und bewahren Sie Metadaten mit Wraps auf.

Probieren Sie diese Lösung im Editor aus

Übersicht

Dekoratoren sind eine der elegantesten und leistungsfähigsten Syntaxfunktionen von Python und ermöglichen es Ihnen, das Verhalten einer Funktion oder Klasse zu ändern, ohne ihren Code dauerhaft zu ändern. Sie werden häufig für übergreifende Anliegen wie die Protokollierung von Ausführungszeiten, die Durchsetzung der Benutzerauthentifizierung, das Zwischenspeichern von Ergebnissen (Memoisierung) und die Überwachung von API-Endpunkten verwendet.

Unter der Haube ist ein Dekorator eine Funktion höherer Ordnung, die eine andere Funktion als Argument verwendet, eine verschachtelte Wrapper-Funktion definiert, die benutzerdefinierte Logik einfügt, und diese Wrapper-Funktion zurückgibt. Python bietet eine saubere Kurzschriftsyntax mit dem „@“-Symbol, um Dekoratoren auf Funktionen anzuwenden und sie optisch elegant zu gestalten.

Wenn Sie Dekoratoren schreiben, möchten Sie normalerweise, dass die dekorierte Funktion eine beliebige Anzahl von Positions- und Schlüsselwortargumenten unterstützt. Sie können dies erreichen, indem Sie die verschachtelte Wrapper-Funktion so gestalten, dass sie „*args“ und „**kwargs“ akzeptiert und an die Zielfunktion übergibt. Darüber hinaus sollten Sie „functools.wraps“ für die Wrapper-Funktion verwenden, um die Dokumentzeichenfolge und Namensmetadaten der ursprünglichen Funktion beizubehalten.

Code- und Ausführungsausgabe

Dieses Skript demonstriert das Schreiben eines Protokollierungsdekorators und das Umschließen einer Funktion zum Überprüfen von Eingaben, Ausgaben und Metadaten.

decorators_tutorial.py
Versuchen Sie es im Editor
from functools import wraps

# 1. Defining a decorator
def log_execution(func):
    @wraps(func) # Preserves original function metadata
    def wrapper(*args, **kwargs):
        print(f"[Log] Calling function: {func.__name__} with args: {args}")
        result = func(*args, **kwargs)
        print(f"[Log] Finished {func.__name__}. Result: {result}")
        return result
    return wrapper

# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
    """Adds two numbers and returns the sum."""
    return a + b

# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)

# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)
Terminal-Ausgabe
[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.

Schrittweise Umsetzung

  • Definieren Sie eine äußere Dekoratorfunktion, die die Zielfunktion als Argument verwendet.
  • Importieren Sie @functools.wraps(func) und wenden Sie es auf Ihre verschachtelte Wrapper-Funktion an, um die ursprünglichen Metadaten zu schützen.
  • Implementieren Sie den Wrapper (*args, **kwargs), um Eingabevariablen zu erfassen, Logik einzufügen und die Zielfunktion aufzurufen.
  • Gibt das Wrapper-Funktionsobjekt aus dem Decorator-Header-Block zurück.
  • Wenden Sie den Dekorator mit @decorator_name direkt über der Zielfunktionssignatur an.

Häufig gestellte Fragen

Warum ist @functools.wraps in Dekorateuren notwendig?

Ohne Wrapper verliert die dekorierte Funktion ihre ursprüngliche Identität (ihre Attribute __name__ und __doc__ werden durch die der verschachtelten Wrapper-Funktion ersetzt), was das Debuggen und die Code-Introspektion erschwert.

Kann ich mehrere Dekoratoren auf eine einzelne Funktion anwenden?

Ja! Sie können Dekoratoren verketten, indem Sie mehrere @-Zeilen stapeln. Python wendet sie von unten nach oben an (am nächsten an der Funktionsdefinition, die zuerst ausgeführt wird).

Verwandte Themen

Empfohlene Python-Ressourcen

Erweitern Sie Ihr Wissen mit zugehörigen interaktiven Tutorials, Spickzetteln und Codevergleichen.