ProgrammierungBackend Entwickler

Was sind höhere Funktionen Dekoratoren in Python, wie ermöglichen sie die Implementierung des 'Wrapper'-Musters, und was ist bei der Arbeit mit Metadaten/Dokumentation von Funktionen zu beachten?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

In Python ist ein höherer Funktionsddekorator eine Funktion, die eine andere Funktion (oder Klasse) entgegennimmt und eine neue Funktion (oder eine neu modifizierte Klasse) zurückgibt. Dekoratoren werden häufig verwendet, um das "Wrapper"-Muster zu implementieren, das es ermöglicht, zusätzliche Logik (z.B. Protokollierung, Caching, Berechtigungsprüfung usw.) zu bestehenden Funktionen hinzuzufügen, ohne ihren ursprünglichen Code zu ändern.

Um den Namen, die Dokumentation und andere Metadaten der ursprünglichen Funktion zu erhalten, wird empfohlen, die Funktion functools.wraps zu verwenden:

import functools def log_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(f'Calling {func.__name__}') return func(*args, **kwargs) return wrapper @log_decorator def add(a, b): """Addiere zwei Zahlen""" return a + b print(add(2, 3)) # Ausgabe: Calling add 5 print(add.__name__) # Ausgabe: add print(add.__doc__) # Ausgabe: Addiere zwei Zahlen

Ein wesentlicher Punkt: Ohne functools.wraps gehen der Name, die Dokumentation und andere Metadaten der umschlossenen Funktion verloren, was sich negativ auf das Debugging und die automatische Dokumentation auswirkt.

Fangfrage.

Was passiert, wenn Sie eine Funktion ohne die Verwendung von functools.wraps dekorieren? Was geschieht mit den Attributen name und doc der Funktion?

Antwort: Sie werden von der inneren Wrapper-Funktion (normalerweise 'wrapper') geerbt, und Sie verlieren die ursprünglichen Metadaten.

def simple_decorator(func): def wrapper(*args, **kwargs): return func(*args, **kwargs) return wrapper @simple_decorator def f(): """Dies ist ein Docstring""" pass print(f.__name__) # Ausgabe: 'wrapper' (NICHT 'f') print(f.__doc__) # Ausgabe: None (nicht 'Dies ist ein Docstring')

Beispiele für tatsächliche Fehler aufgrund von Unkenntnis der Details des Themas.


Geschichte

Im Projekt wurde ein komplexes System von Dekoratoren für das Protokollieren von API-Endpunkten implementiert, aber functools.wraps nicht angewendet. Infolgedessen wurden bei der automatischen Dokumentation (Swagger/OpenAPI) und bei Introspektionswerkzeugen alle Endpunktnamen als 'wrapper' angezeigt, und die Dokumentation ging verloren. Dies erschwerte die Wartung, das Testen und die Unterstützung erheblich.


Geschichte

Beim Schreiben von Unit-Tests mit pytest trat ein Fehler bei der automatischen Entdeckung von Tests auf: Testfunktionen, die mit ihren eigenen Dekoratoren ohne wraps dekoriert waren, wurden nicht entdeckt, da ihr name inkorrekt war. Der Grund ist, dass pytest nach Funktionen anhand ihres Namens sucht.


Geschichte

Bei der Verfolgung des Ausnahme-Stacktraces (traceback) zeigte der Stack-Trac immer auf "wrapper", und es war unmöglich zu verstehen, welche Funktion den Fehler verursacht hat, da die Root-Metadaten aufgrund des Fehlens von functools.wraps in benutzerdefinierten Dekoratoren verloren gingen.