6.1 Decorators für Klassenmethoden
Decorators können auch für Klassenmethoden verwendet werden. Es ist wichtig,
daran zu denken, dass für Klassenmethoden die Argumente richtig übergeben werden müssen:
self
oder cls
.
Die Feinheiten der Arbeit mit Klassen haben wir noch nicht behandelt, aber es wäre schön, wenn ihr wüsstet, dass Decorators diese Möglichkeit haben.
def log_method_call(func):
def wrapper(self, *args, **kwargs):
print(f"Aufruf der Methode {func.__name__}")
return func(self, *args, **kwargs)
return wrapper
class MyClass:
@log_method_call
def say_hello(self):
print("Hello from MyClass!")
obj = MyClass()
obj.say_hello()
Erklärung
Decorator (log_method_call)
: Dieser Decorator nimmt die Methode
func
und gibt eine neue Funktion wrapper
zurück, die eine Nachricht vor
dem Aufruf der Methode ausgibt.
Klassenmethode mit Decorator (say_hello)
: Die Methode say_hello
ist mit dem Decorator log_method_call
umhüllt, was beim Aufruf ein zusätzliches Verhalten
hinzufügt.
Ausgabe:
Aufruf der Methode say_hello
Hello from MyClass!
6.2 Mehrere Decorators
Du kannst mehrere Decorators für eine Funktion verwenden und sie aufeinander aufbauen. Die Decorators werden in umgekehrter Reihenfolge ihrer Deklaration angewendet.
def decorator1(func):
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()
Erklärung
Decorators (decorator1 und decorator2)
: Diese Decorators
fügen ihre Nachrichten vor dem Aufruf der Funktion func
hinzu.
Funktion mit Decorators (say_hello)
: Die Funktion say_hello
ist mit beiden Decorators umhüllt. Zuerst wird decorator2
angewendet, dann
decorator1
.
Ausgabe:
# Decorator 1
# Decorator 2
Hello!
6.3 Eingebaute Decorators
Python bietet mehrere eingebaute Decorators für Standardaufgaben, wie statische Methoden, Klassenmethoden und Eigenschaften.
@staticmethod
Der Decorator @staticmethod
wird verwendet, um eine statische
Methode zu erstellen, die keine Instanz der Klasse für den Aufruf erfordert.
class MyClass:
@staticmethod
def static_method():
print("Das ist eine statische Methode.")
MyClass.static_method()
@classmethod
Der Decorator @classmethod
wird verwendet, um eine Klassenmethode zu erstellen,
die die Klasse (und nicht die Instanz) als erstes Argument akzeptiert.
class MyClass:
@classmethod
def class_method(cls):
print(f"Das ist eine Klassenmethode {cls.__name__}.")
MyClass.class_method()
@property
Der Decorator @property
wird verwendet, um Getter,
Setter und Deleter für Attribute zu erstellen.
class MyClass:
def __init__(self, value):
self.hidden_value = value
@property
def value(self):
return self.hidden_value
@value.setter
def value(self, new_value):
self.hidden_value = new_value
obj = MyClass(10)
print(obj.value) # Ausgabe: 10
obj.value = 20
print(obj.value) # Ausgabe: 20
Diese sind eingebaute Decorators, ihre richtige Funktionalität wird durch den Python-Interpreter selbst bereitgestellt.
6.4 Anwendungsbeispiele von Decorators
Logging
Decorators können zum Logging von Funktions- und Methodenaufrufen verwendet werden.
def log_call(func):
def wrapper(*args, **kwargs):
print(f"Aufruf der Funktion {func.__name__} mit Argumenten {args} und {kwargs}")
return func(*args, **kwargs)
return wrapper
@log_call
def add(x, y):
return x + y
print(add(2, 3))
Zugangskontrolle
Decorators können zur Zugangskontrolle zu Funktionen und Methoden verwendet werden.
def require_authentication(func):
def wrapper(*args, **kwargs):
if not args[0].is_authenticated:
raise PermissionError("Benutzer nicht authentifiziert.")
return func(*args, **kwargs)
return wrapper
class User:
def __init__(self, is_authenticated):
self.is_authenticated = is_authenticated
@require_authentication
def view_profile(self):
print("Benutzerprofil")
user = User(is_authenticated=True)
user.view_profile() # Erfolgreicher Aufruf
user2 = User(is_authenticated=False)
user2.view_profile() # PermissionError: Benutzer nicht authentifiziert.
Caching
Decorators können für das Caching von Funktionsergebnissen verwendet werden.
def cache(func):
cached_results = {}
def wrapper(*args):
if args in cached_results:
return cached_results[args]
result = func(*args)
cached_results[args] = result
return result
return wrapper
@cache
def fib(n):
if n < 2:
return n
return fib(n - 1) + fib(n - 2)
print(fib(35))
GO TO FULL VERSION