Dekoratoren in Python
Dieser Artikel erklärt Dekoratoren in Python.
YouTube Video
Dekoratoren in Python
Python-Dekoratoren sind eine leistungsstarke Funktion, die verwendet wird, um Funktionen oder Methoden zusätzliche Funktionalitäten hinzuzufügen. Dekoratoren ermöglichen es, neue Funktionalitäten hinzuzufügen, ohne den bestehenden Code zu verändern, was die Wiederverwendbarkeit und Wartbarkeit des Codes verbessert.
Grundlagen der Dekoratoren
Python-Dekoratoren funktionieren, indem sie eine Funktion als Argument nehmen und eine neue Funktion mit zusätzlicher Funktionalität zurückgeben. Mit Dekoratoren können Sie Vor- oder Nachbearbeitungen leicht zu Funktionen hinzufügen.
Ohne Dekoratoren erfordert das Ändern des Verhaltens einer Funktion, dass die Funktion selbst direkt bearbeitet wird. Mit Dekoratoren können Sie die Funktionalität erweitern, ohne die ursprüngliche Implementierung zu ändern.
Grundlegende Struktur eines Dekorators
1def my_decorator(func):
2 def wrapper():
3 print("Before the function call")
4 func()
5 print("After the function call")
6 return wrapper
7
8@my_decorator
9def say_hello():
10 print("Hello!")
11
12say_hello()
In diesem Beispiel dient die Funktion my_decorator
als Dekorator und umschließt die Funktion say_hello
. Der Dekorator wird mit der Syntax @my_decorator
angewendet, und wenn say_hello()
aufgerufen wird, wird die vom Dekorator bereitgestellte Vor- und Nachbearbeitung automatisch ausgeführt.
Wie Dekoratoren funktionieren
Dekoratoren funktionieren in den folgenden Schritten.
-
Der Dekorator nimmt eine Funktion (oder Methode) als Argument.
-
Er definiert eine Wrapper-Funktion, um die ursprüngliche Funktion auszuführen.
-
Die Wrapper-Funktion führt zusätzliche Verarbeitung vor oder nach der Ausführung der ursprünglichen Funktion durch.
-
Der Dekorator gibt die Wrapper-Funktion zurück. Das Ergebnis ist, dass die ursprüngliche Funktion durch eine neue, dekorierte Funktion ersetzt wird.
Dekoratoren für Funktionen mit Argumenten
Wenn ein Dekorator auf eine Funktion mit Argumenten angewendet wird, muss die Wrapper-Funktion so angepasst werden, dass sie diese Argumente akzeptiert.
1def my_decorator(func):
2 def wrapper(*args, **kwargs):
3 print("Before the function call")
4 result = func(*args, **kwargs)
5 print("After the function call")
6 return result
7 return wrapper
8
9@my_decorator
10def greet(name):
11 print(f"Hello, {name}!")
12
13greet("Alice")
Durch die Verwendung von *args
und **kwargs
ist es möglich, Funktionen zu behandeln, die eine beliebige Anzahl von Argumenten und Schlüsselwort-Argumenten akzeptieren. Dies ermöglicht es, Dekoratoren generisch auf Funktionen mit beliebigen Arten von Argumenten anzuwenden.
Beispiele für die Anwendung von Dekoratoren
Dekorator für Logging
Dekoratoren werden oft verwendet, um Logging-Funktionalitäten hinzuzufügen. Zum Beispiel kann durch die Erstellung eines Dekorators, der vor und nach der Ausführung einer Funktion Logdaten erfasst, aufgezeichnet werden, wann die Funktion aufgerufen wird und wie lange sie zur Ausführung benötigt.
1import time
2
3def log_time(func):
4 def wrapper(*args, **kwargs):
5 start_time = time.time()
6 print(f"Calling function '{func.__name__}'...")
7 result = func(*args, **kwargs)
8 end_time = time.time()
9 print(f"Function '{func.__name__}' completed in {end_time - start_time} seconds")
10 return result
11 return wrapper
12
13@log_time
14def long_task(duration):
15 time.sleep(duration)
16 print("Task completed!")
17
18long_task(2)
In diesem Beispiel misst der log_time
-Dekorator die Ausführungszeit einer Funktion und gibt sie als Log aus. Die Funktion long_task
wird mit dem Dekorator umhüllt, und ihre Ausführungszeit wird zur Laufzeit aufgezeichnet.
Dekorator für die Berechtigungsverwaltung
Dekoratoren können auch für die Berechtigungsverwaltung verwendet werden. Zum Beispiel kann die Verarbeitung eingeschränkt werden, indem geprüft wird, ob ein Benutzer bestimmte Berechtigungen besitzt.
1def requires_permission(user_role):
2 def decorator(func):
3 def wrapper(*args, **kwargs):
4 if user_role != "admin":
5 print("Permission denied!")
6 return
7 return func(*args, **kwargs)
8 return wrapper
9 return decorator
10
11@requires_permission("admin")
12def delete_user(user_id):
13 print(f"User {user_id} has been deleted.")
14
15delete_user(123) # Executed
16delete_user = requires_permission("guest")(delete_user)
17delete_user(456) # Permission denied!
Der Dekorator requires_permission
schränkt die Ausführung einer Funktion basierend auf der Rolle eines Benutzers ein. Durch die Konsolidierung solcher Logik in einem Dekorator kann verhindert werden, dass die Berechtigungsverwaltungslogik über den gesamten Code verstreut ist, was die Lesbarkeit erhöht.
Verschachtelung von Dekoratoren
Es ist möglich, mehrere Dekoratoren anzuwenden. Wenn mehrere Dekoratoren auf eine einzelne Funktion angewandt werden, werden sie in der Reihenfolge von oben nach unten ausgeführt.
1def uppercase(func):
2 def wrapper(*args, **kwargs):
3 result = func(*args, **kwargs)
4 return result.upper()
5 return wrapper
6
7def exclaim(func):
8 def wrapper(*args, **kwargs):
9 result = func(*args, **kwargs)
10 return result + "!"
11 return wrapper
12
13@uppercase
14@exclaim
15def greet(name):
16 return f"Hello, {name}"
17
18print(greet("Alice")) # "HELLO, ALICE!"
In diesem Beispiel werden zwei Dekoratoren auf die Funktion greet
angewandt. Der Dekorator @exclaim
fügt am Ende des Strings ein Ausrufezeichen hinzu, und anschließend konvertiert @uppercase
den String in Großbuchstaben.
Dekoratoren für Klassenmethoden
Dekoratoren können auch mit Klassenmethoden verwendet werden. Dies ist besonders nützlich, wenn das Verhalten von Methoden innerhalb einer Klasse gesteuert werden soll. Beim Anwenden von Dekoratoren auf Klassenmethoden sollte auf Argumente wie self
oder cls
geachtet werden.
1def log_method_call(func):
2 def wrapper(self, *args, **kwargs):
3 print(f"Calling method '{func.__name__}'...")
4 return func(self, *args, **kwargs)
5 return wrapper
6
7class MyClass:
8 @log_method_call
9 def greet(self, name):
10 print(f"Hello, {name}")
11
12obj = MyClass()
13obj.greet("Bob")
In diesem Beispiel wird der Dekorator log_method_call
auf die Methode greet
angewandt, um ein Log auszugeben, wenn die Methode aufgerufen wird.
Vorsichtsmaßnahmen bei der Verwendung von Dekoratoren
Es gibt einige Überlegungen bei der Verwendung von Dekoratoren. Dekoratoren können möglicherweise den Namen und die Dokumentationszeichenkette der ursprünglichen Funktion (z. B. __name__
oder __doc__
) ändern, daher wird empfohlen, functools.wraps
zu verwenden, um diese Informationen beizubehalten.
1import functools
2
3def my_decorator(func):
4 @functools.wraps(func)
5 def wrapper(*args, **kwargs):
6 print("Before the function call")
7 return func(*args, **kwargs)
8 return wrapper
Die Verwendung von @functools.wraps
stellt sicher, dass die Metadaten der ursprünglichen Funktion korrekt an die Wrapper-Funktion übergeben werden.
Zusammenfassung
Python-Dekoratoren sind ein sehr leistungsstarkes Werkzeug, mit dem Sie Funktionen und Methoden prägnant zusätzliche Funktionalitäten hinzufügen können. Sie können in verschiedenen Szenarien verwendet werden, um Code-Duplikation zu reduzieren und die Wartbarkeit sowie Wiederverwendbarkeit zu verbessern. Indem Sie verstehen, wie Dekoratoren funktionieren, können Sie effizienteren und flexibleren Code schreiben.
Sie können den obigen Artikel mit Visual Studio Code auf unserem YouTube-Kanal verfolgen. Bitte schauen Sie sich auch den YouTube-Kanal an.