Dekoratoren sind ein wichtiger Teil von Python. Einfach ausgedrückt: Es sind Funktionen, die die Funktionalität anderer Funktionen verändern. Sie helfen, unseren Code kürzer und pythonischer zu machen. Die meisten Anfänger wissen nicht, wo sie sie einsetzen sollen, deshalb werde ich einige Bereiche vorstellen, in denen Dekoratoren deinen Code sauberer machen können. Zuerst besprechen wir, wie man seine eigenen Dekoratoren schreibt.
Dies ist wahrscheinlich eines der schwierigsten Konzepte, die man beherrschen muss. Wir werden es Schritt für Schritt besprechen, damit du es vollständig verstehst.
Alles ist ein Objekt
Zuerst wollen wir Funktionen in Python verstehen:
Funktionen innerhalb von Funktionen definieren
Das waren die Grundlagen von Funktionen. Bringen wir dein Wissen einen Schritt weiter. In Python können wir eine Funktion innerhalb einer anderen Funktion definieren:
Jetzt wissen wir, dass wir andere Funktionen innerhalb einer Funktion definieren können. Das heißt: Wir können verschachtelte Funktionen erstellen. Jetzt musst du noch ein wenig mehr lernen: Funktionen können auch Funktionen zurückgeben.
Funktionen aus Funktionen zurückgeben
Eigentlich ist es nicht nötig, eine andere Funktion innerhalb einer Funktion auszuführen; wir können sie auch als Ausgabe zurückgeben:
Schau dir diesen Code noch einmal an. In der if/else-Anweisung geben wir greet und welcome zurück, nicht greet() und welcome(). Warum ist das so? Das liegt daran, dass die Funktion ausgeführt wird, wenn man ein Klammernpaar dahinter setzt; wenn man jedoch keine Klammern dahinter setzt, kann sie weitergegeben und anderen Variablen zugewiesen werden, ohne dass sie ausgeführt wird. Verstehst du? Lass es mich etwas detaillierter erklären.
Wenn wira = hi(),hi() schreiben,wird es ausgeführt, und da der Parameter name standardmäßig yasoob ist, wird die Funktiongreet()zurückgegeben.
-
Wir können auchhi()(), was Folgendes ausgibt:jetzt bist du in der greet()-Funktion。
-
Wenn wir die Anweisung zua = hi(name = "ali")ändern, dannwelcome()wird die Funktion zurückgegeben.
Eine Funktion als Argument an eine andere Funktion übergeben
Jetzt hast du all das nötige Wissen, um zu lernen, was Dekoratoren wirklich sind. Dekoratoren ermöglichen es dir, Code vor und nach einer Funktion auszuführen.
Dein erster Dekorator
Im vorherigen Beispiel haben wir tatsächlich bereits einen Dekorator erstellt! Jetzt lass uns den vorherigen Dekorator ändern und ein etwas nützlicheres Programm schreiben:
Siehst du es? Wir haben gerade die Prinzipien angewendet, die wir früher gelernt haben. Genau das machen Dekoratoren in Python! Sie umhüllen eine Funktion und ändern ihr Verhalten auf die eine oder andere Weise. Jetzt fragst du dich vielleicht, in unserem Code haben wir das@Symbol nicht verwendet? Das ist nur eine Kurzform, um eine dekorierte Funktion zu erzeugen. So verwenden wir@um den vorherigen Code auszuführen:
Hoffentlich hast du jetzt ein grundlegendes Verständnis dafür, wie Python-Dekoratoren funktionieren. Es gibt ein Problem, wenn wir den folgenden Code ausführen:
print(a_function_requiring_decoration.__name__) # Output: wrapTheFunction
Das ist nicht, was wir wollten! Die Ausgabe sollte "a_function_requiring_decoration" sein. Hier wurde die Funktion durch warpTheFunction ersetzt. Sie hat den Namen und den Docstring unserer Funktion überschrieben. Glücklicherweise stellt uns Python eine einfache Funktion zur Verfügung, um dieses Problem zu lösen, nämlich functools.wraps. Ändern wir das vorherige Beispiel so, dass es functools.wraps verwendet:
Das ist jetzt viel besser. Als Nächstes lernen wir einige häufige Anwendungsfälle von Dekoratoren kennen.
Bauplan-Spezifikation:
Hinweis:@wrapsSie akzeptiert eine zu dekorierende Funktion und fügt Funktionalität hinzu, um den Funktionsnamen, Docstring, die Argumentliste und so weiter zu kopieren. Dadurch können wir innerhalb des Dekorators auf die Attribute der Funktion vor der Dekoration zugreifen.
Anwendungsfälle
Schauen wir uns nun an, wo Dekoratoren wirklich glänzen, und wie ihre Verwendung die Verwaltung einiger Dinge erleichtert.
Authorization
Dekoratoren können dabei helfen zu prüfen, ob jemand berechtigt ist, einen Endpunkt einer Webanwendung zu verwenden. Sie werden in den Web-Frameworks Flask und Django stark genutzt. Hier ist ein Beispiel für die Verwendung einer dekoratorbasierten Autorisierung:
Protokollierung
Logging ist ein weiteres Highlight bei der Verwendung von Dekoratoren. Hier ist ein Beispiel:
Ich bin mir sicher, dass du bereits an eine weitere clevere Verwendung von Dekoratoren denkst.
Dekoratoren mit Parametern
Denke darüber nach: Ist @wraps nicht auch ein Dekorator? Aber er nimmt einen Parameter, genau wie jede gewöhnliche Funktion es kann. Warum machen wir das also nicht auch? Das liegt daran, dass du, wenn du die Syntax @my_decorator verwendest, eine Wrapper-Funktion anwendest, die eine einzelne Funktion als Argument nimmt. Denke daran: Alles in Python ist ein Objekt, und das schließt Funktionen ein! Mit diesem Gedanken können wir eine Funktion schreiben, die eine Wrapper-Funktion zurückgibt.
Dekoratoren in Funktionen einbetten
Kehren wir zum Logging-Beispiel zurück und erstellen eine Wrapper-Funktion, mit der wir eine Logdatei für die Ausgabe angeben können.
Dekorator-Klassen
Jetzt haben wir einen logit-Dekorator, der für die Produktion geeignet ist, aber wenn bestimmte Teile unserer Anwendung noch fragil sind, können Ausnahmen eine dringendere Aufmerksamkeit erfordern. Zum Beispiel möchten Sie manchmal nur in eine Datei protokollieren. Andere Male möchten Sie ein Problem, das Ihre Aufmerksamkeit erregt, per E-Mail senden und gleichzeitig ein Protokoll für die Aufzeichnung führen. Dies ist ein Szenario für die Verwendung von Vererbung, aber bisher haben wir nur Funktionen gesehen, die zum Erstellen von Dekoratoren verwendet werden.
Glücklicherweise können auch Klassen verwendet werden, um Dekoratoren zu erstellen. Lassen Sie uns also jetzt logit mithilfe einer Klasse statt einer Funktion neu aufbauen.
Diese Implementierung hat den zusätzlichen Vorteil, sauberer zu sein als der Ansatz mit verschachtelter Funktion, und das Umwickeln einer Funktion verwendet weiterhin die gleiche Syntax wie zuvor:
@logit()
def myfunc1():
pass
Jetzt erstellen wir eine Unterklasse von logit, um E-Mail-Funktionalität hinzuzufügen (obwohl das Thema E-Mail hier nicht weiter ausgeführt wird).
Ab jetzt hat @email_logit denselben Effekt wie @logit, aber zusätzlich zum Logging wird auch eine E-Mail an den Administrator gesendet.
Originale Artikeladresse: https://eastlakeside.gitbooks.io/interpy-zh/content/decorators/