Ein Leitfaden zu Python-Dekoratoren für fortgeschrittene Programmierer
Python-Dekoratoren sind ein leistungsstarkes und flexibles Werkzeug zum Ändern des Verhaltens von Funktionen oder Methoden. Sie ermöglichen es Programmierern, die Funktionalität aufrufbarer Objekte auf saubere, lesbare und wartbare Weise zu erweitern oder zu ändern. Dieser Artikel untersucht fortgeschrittene Konzepte im Zusammenhang mit Python-Dekoratoren, einschließlich verschachtelter Dekoratoren, Dekoratorargumente und klassenbasierter Dekoratoren.
Was sind Dekorateure?
Dekoratoren sind Funktionen, die das Verhalten einer anderen Funktion ändern. Sie umschließen eine andere Funktion, um deren Verhalten zu erweitern, ohne ihren Code explizit zu ändern. Dekoratoren werden mit der Syntax @decorator_name
definiert und über der Funktionsdefinition platziert.
Grundlegende Dekorator-Syntax
Ein einfacher Dekorator verwendet eine Funktion als Argument, definiert eine innere Funktion, die ein bestimmtes Verhalten hinzufügt, und gibt dann die innere Funktion zurück.
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
say_hello()
Dekoratorfunktionen mit Argumenten
Dekoratoren können flexibler sein, indem sie Argumente akzeptieren. Um einen solchen Dekorator zu erstellen, müssen Sie eine Funktion schreiben, die einen Dekorator zurückgibt. Dadurch können Sie den Dekoratoren dynamischeres Verhalten verleihen.
def repeat(num_times):
def decorator_repeat(func):
def wrapper(*args, **kwargs):
for _ in range(num_times):
func(*args, **kwargs)
return wrapper
return decorator_repeat
@repeat(num_times=3)
def greet(name):
print(f"Hello, {name}!")
greet("Alice")
Verschachtelte Dekorateure
Dekoratoren können verschachtelt werden, um mehrere Verhaltensweisen zu kombinieren. Beispielsweise können wir zwei oder mehr Dekoratoren für eine einzelne Funktion verwenden.
def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def repeat_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + result
return wrapper
@repeat_decorator
@uppercase_decorator
def say_word(word):
return word
print(say_word("hello"))
Klassenbasierte Dekoratoren
In Python können Dekoratoren auch als Klassen implementiert werden, indem die Methode __call__
verwendet wird. Klassenbasierte Dekoratoren sind nützlich, wenn Sie eine komplexere Statusverwaltung und ein komplexeres Verhalten benötigen.
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"Call {self.num_calls} of {self.func.__name__!r}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello()
say_hello()
Verwenden von functools.wraps
zum Beibehalten von Metadaten
Wenn Sie Dekoratoren schreiben, verliert die dekorierte Funktion ihre ursprünglichen Metadaten, wie z. B. ihren Namen und ihre Docstring. Mit dem Dekorator functools.wraps
können die Metadaten der ursprünglichen Funktion in die Wrapper-Funktion kopiert werden.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Wrapper function executed before", func.__name__)
return func(*args, **kwargs)
return wrapper
@my_decorator
def display_info(name, age):
"""Displays name and age."""
print(f"display_info ran with arguments ({name}, {age})")
print(display_info.__name__) # Output: display_info
print(display_info.__doc__) # Output: Displays name and age.
Abschluss
Python-Dekoratoren sind eine leistungsstarke Funktion, die flexibles Codedesign und Verhaltensänderungen ermöglicht. Fortgeschrittene Verwendungsmöglichkeiten wie verschachtelte Dekoratoren, Dekoratoren mit Argumenten und klassenbasierte Dekoratoren können Python-Programmen noch mehr Funktionalität und Lesbarkeit verleihen. Durch das Verständnis und die richtige Verwendung von Dekoratoren können Entwickler prägnanteren, effizienteren und lesbareren Code schreiben.