Python-Dekoratoren
Ein Dekorator ist ein fortgeschrittenes Merkmal in Python, mit demdie Funktionalität von Funktionen oder Klassen dynamisch erweitert werden kann, ohne den ursprünglichen Funktionscode zu ändern。
Im Wesentlichen ist ein Dekorator eine Funktion: Er erhält eine Funktion als Argument und gibt eine neue Funktion zurück (normalerweise eine erweiterte Version der ursprünglichen Funktion).
Dekoratoren werden mit der@decorator_name-Syntax vor einer Funktions- oder Methodendefinition verwendet.
Python bietet auch einige integrierte Dekoratoren, wie z. B.@staticmethodund@classmethod。
Häufige Anwendungsfälle:
- Protokollierung:Funktionsaufrufinformationen, Parameter und Rückgabewerte aufzeichnen
- Leistungsstatistiken:Ausführungszeit der Funktion messen
- Zugriffskontrolle:Zugriffsberechtigungen für Funktionen einschränken
- Caching:Funktionsergebnisse zwischenspeichern, um die Leistung zu verbessern
Grundlegende Syntax
Die Kernidee eines Dekorators ist:eine Funktion zu verwenden, um eine andere Funktion zu "umschließen"。
Syntax
def wrapper(*args, **kwargs):
# Vor dem Aufruf
print("Vor der Ausführung")
result = original_function(*args, **kwargs)
# Nach dem Aufruf
print("Nach der Ausführung")
return result
return wrapper
@decorator_function
def target_function():
print("Ausführung der Originalfunktion")
Erklärung:
decorator_function: Dekorator-Funktion (empfängt die Originalfunktion)wrapper: Wrapper-Funktion (wird tatsächlich ausgeführt)@decorator_function: entspricht dem Ersetzen einer Funktion
Äquivalente Form:
target_function = decorator_function(target_function)
👉 Beim Aufruftarget_function(), was tatsächlich ausgeführt wird, istwrapper()
Dekoratoren verwenden
Dekoratoren werden mit dem@syntaktischen Zucker angewendet, der vor der Funktionsdefinition platziert wird:
@time_logger
def target_function():
pass
Entspricht:
def target_function():
pass
target_function = time_logger(target_function)
Dieser Mechanismus ermöglicht es uns, Funktionalität (wie Protokollierung, Berechtigungen usw.) einheitlich hinzuzufügen, ohne die ursprüngliche Funktion zu ändern.
Beispiel: Logs ausgeben
def wrapper():
print("Vor der Funktionsausführung")
func()
print("Nach der Funktionsausführung")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Ausgabe:
函数执行前 Hello! 函数执行后
my_decoratorEmpfängtsay_hello@my_decoratorErsetzt die ursprüngliche Funktion
Dekoratoren mit Parametern
Wenn die ursprüngliche Funktion Parameter hat, müssen Sie in derwrapperVerwenden Sie*args, **kwargs:
Beispiel
def wrapper(*args, **kwargs):
print("Vor der Ausführung")
func(*args, **kwargs)
print("Nach der Ausführung")
return wrapper
@my_decorator
def greet(name):
print(f"Hallo, {name}!")
greet("Alice")
Ausgabe:
执行前 Hello, Alice! 执行后
Erklärung:Verwenden*args, **kwargskann Funktionen mit beliebig vielen Parametern aufnehmen.
Dekoratoren mit Parametern (Fortgeschritten)
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello()
Erklärung:Dies ist eine "Dekorator-Fabrik"; die äußere Funktion dient zum Empfangen von Parametern.
Hello! Hello! Hello!
Klassendekoratoren
Zusätzlich zu Funktionen können Dekoratoren auch auf Klassen angewendet werden.
Ein Klassendekorator empfängt eine Klasse und gibt eine modifizierte Klasse oder eine Wrapper-Klasse zurück.
- Klassenmethoden erweitern
- Den Instanziierungsprozess steuern
- Funktionalität wie Singletons und Logging implementieren
Funktionsbasierte Klassendekoratoren
Beispiel
class Wrapper:
def __init__(self, *args, **kwargs):
self.wrapped = cls(*args, **kwargs)
def __getattr__(self, name):
return getattr(self.wrapped, name)
def display(self):
print("Vor dem Aufruf")
self.wrapped.display()
print("Nach dem Aufruf")
return Wrapper
@log_class
class MyClass:
def display(self):
print("Ursprüngliche Methode")
obj = MyClass()
obj.display()
Before call Original method After call
Klassenbasierte Klassendekoratoren
Beispiel: Singleton-Muster
def __init__(self, cls):
self.cls = cls
self.instance = None
def __call__(self, *args, **kwargs):
if self.instance is None:
self.instance = self.cls(*args, **kwargs)
return self.instance
@SingletonDecorator
class Database:
def __init__(self):
print("Initialisierung")
db1 = Database()
db2 = Database()
print(db1 is db2)
初始化 True
Eingebaute Dekoratoren
Häufig verwendete eingebaute Dekoratoren:
- @staticmethod: definiert eine statische Methode
- @classmethod: definiert eine Klassenmethode
- @property: verwandelt eine Methode in eine Eigenschaft
Beispiel
@staticmethod
def static_method():
print("Static method")
@classmethod
def class_method(cls):
print(cls.__name__)
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
Mehrere Decorators stapeln
Mehrere Decoratorsumhüllen die Funktion während der Definitionsphase von unten nach oben,und werden während der Aufrufphase von oben nach unten ausgeführt:
Beispiel
def wrapper():
print("Decorator 1")
func()
return wrapper
def decorator2(func):
def wrapper():
print("Decorator 2")
func()
return wrapper
@decorator1
@decorator2
def say_hello():
print("Hello!")
say_hello()
Endgültige Ausgabe:
Decorator 1 Decorator 2 Hello!
Kernzusammenfassung
Decorator = a function that wraps a function + extending functionality without modifying the original code
- Die @-Syntax ist im Wesentlichen ein Funktionsersatz
- wrapper ist die Funktion, die tatsächlich ausgeführt wird
- Es wird empfohlen, *args, **kwargs für größere Vielseitigkeit zu verwenden
- Unterstützt Funktionen, Klassen und sogar Dekoratoren mit Parametern