Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern

PythonPythonBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Python-Dekorateure (Decorators) sind ein mächtiges Werkzeug, das es Ihnen ermöglicht, das Verhalten von Funktionen zu ändern, ohne deren Kernfunktionalität zu verändern. In diesem Tutorial tauchen wir in die Welt der Dekorateure ein und untersuchen, wie Sie sie nutzen können, um die Leistung, das Logging und die Gesamtfunktionalität Ihres Python-Codes zu verbessern.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/AdvancedTopicsGroup(["Advanced Topics"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/arguments_return("Arguments and Return Values") python/FunctionsGroup -.-> python/lambda_functions("Lambda Functions") python/AdvancedTopicsGroup -.-> python/decorators("Decorators") python/AdvancedTopicsGroup -.-> python/context_managers("Context Managers") subgraph Lab Skills python/function_definition -.-> lab-415777{{"Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern"}} python/arguments_return -.-> lab-415777{{"Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern"}} python/lambda_functions -.-> lab-415777{{"Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern"}} python/decorators -.-> lab-415777{{"Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern"}} python/context_managers -.-> lab-415777{{"Wie man Dekorateure (Decorators) in Python verwendet, um das Verhalten von Funktionen zu ändern"}} end

Python-Dekorateure verstehen

Python-Dekorateure (Decorators) sind ein mächtiges Feature, das es Ihnen ermöglicht, das Verhalten einer Funktion zu ändern, ohne ihren Quellcode zu verändern. Sie sind eine Möglichkeit, eine Funktion mit einer anderen Funktion zu umhüllen und der ursprünglichen Funktion zusätzliche Funktionalität hinzuzufügen.

Was sind Dekorateure?

Dekorateure sind eine Möglichkeit, das Verhalten einer Funktion oder Klasse zu ändern. Sie werden mit dem @-Symbol definiert, gefolgt von der Dekoratorfunktion, und direkt vor der Funktions- oder Klassendefinition platziert.

Hier ist ein Beispiel für eine einfache Dekoratorfunktion:

def uppercase(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

@uppercase
def say_hello():
    return "hello"

print(say_hello())  ## Output: HELLO

In diesem Beispiel nimmt die uppercase-Dekoratorfunktion eine Funktion func als Argument entgegen und gibt eine neue Funktion wrapper zurück, die func aufruft und dann das Ergebnis in Großbuchstaben umwandelt.

Wie Dekorateure funktionieren

Dekorateure funktionieren, indem sie das Verhalten einer Funktion zur Laufzeit ändern. Wenn Sie einen Dekorator auf eine Funktion anwenden, wird die ursprüngliche Funktion durch das Ergebnis der Dekoratorfunktion ersetzt. Das bedeutet, dass wenn Sie die dekorierte Funktion aufrufen, Sie tatsächlich die Wrapper-Funktion aufrufen, die der Dekorator zurückgegeben hat.

Der Prozess der Anwendung eines Dekorators kann in die folgenden Schritte unterteilt werden:

  1. Die Dekoratorfunktion wird definiert, die eine Funktion als Argument nimmt und eine neue Funktion zurückgibt.
  2. Das @-Symbol wird verwendet, um den Dekorator auf eine Funktion anzuwenden.
  3. Wenn die dekorierte Funktion aufgerufen wird, wird die vom Dekorator zurückgegebene Wrapper-Funktion anstelle der ursprünglichen Funktion ausgeführt.

Vorteile der Verwendung von Dekoratoren

Dekorateure bieten mehrere Vorteile:

  1. Code-Wiederverwendung: Dekorateure ermöglichen es Ihnen, die gleiche Funktionalität über mehrere Funktionen hinweg wiederzuverwenden, wodurch Ihr Code weniger redundant wird (DRY - Don't Repeat Yourself).
  2. Trennung von Anliegen: Dekorateure helfen Ihnen, die Kernfunktionalität einer Funktion von der zusätzlichen Funktionalität zu trennen, die Sie hinzufügen möchten, wodurch Ihr Code modularer und leichter wartbar wird.
  3. Flexibilität: Dekorateure können einfach von einer Funktion hinzugefügt oder entfernt werden, wodurch Sie bestimmte Verhaltensweisen einfach aktivieren oder deaktivieren können.
  4. Lesbarkeit: Dekorateure machen Ihren Code lesbarer und selbsterklärender, da der Name des Dekorators deutlich angibt, welche zusätzliche Funktionalität einer Funktion hinzugefügt wird.

Häufige Anwendungsfälle für Dekorateure

Dekorateure können in einer Vielzahl von Szenarien verwendet werden, darunter:

  • Logging: Hinzufügen von Logging-Funktionalität zu einer Funktion.
  • Caching: Zwischenspeichern der Ergebnisse einer Funktion, um die Leistung zu verbessern.
  • Authentifizierung: Prüfen, ob ein Benutzer autorisiert ist, auf eine Funktion zuzugreifen.
  • Zeitmessung: Messen der Ausführungszeit einer Funktion.
  • Fehlerbehandlung: Bereitstellen einer benutzerdefinierten Fehlerbehandlung für eine Funktion.

Im nächsten Abschnitt werden wir untersuchen, wie Sie Dekorateure anwenden können, um das Verhalten von Funktionen in Python zu ändern.

Anwendung von Dekoratoren zur Änderung des Funktionsverhaltens

Nachdem wir nun ein grundlegendes Verständnis davon haben, was Dekorateure (Decorators) sind und wie sie funktionieren, wollen wir untersuchen, wie wir sie nutzen können, um das Verhalten von Funktionen in Python zu ändern.

Übergeben von Argumenten an Dekorateure

Dekorateure können auch Argumente akzeptieren, was es Ihnen ermöglicht, ihr Verhalten anzupassen. Hier ist ein Beispiel für einen Dekorator, der ein Argument nimmt, um die Schreibweise der Ausgabe zu steuern:

def case_converter(case):
    def decorator(func):
        def wrapper():
            result = func()
            if case == "upper":
                return result.upper()
            elif case == "lower":
                return result.lower()
            else:
                return result
        return wrapper
    return decorator

@case_converter("upper")
def say_hello():
    return "hello"

print(say_hello())  ## Output: HELLO

@case_converter("lower")
def say_goodbye():
    return "GOODBYE"

print(say_goodbye())  ## Output: goodbye

In diesem Beispiel nimmt der case_converter-Dekorator ein Argument case entgegen, das bestimmt, ob die Ausgabe in Groß- oder Kleinbuchstaben umgewandelt werden soll.

Dekorieren von Funktionen mit Argumenten

Dekorateure können auch verwendet werden, um das Verhalten von Funktionen zu ändern, die Argumente nehmen. Hier ist ein Beispiel:

def log_function_call(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__} with args={args} and kwargs={kwargs}")
        return func(*args, **kwargs)
    return wrapper

@log_function_call
def add_numbers(a, b):
    return a + b

print(add_numbers(2, 3))  ## Output:
## Calling add_numbers with args=(2, 3) and kwargs={}
## 5

In diesem Beispiel umhüllt der log_function_call-Dekorator die add_numbers-Funktion und protokolliert den Funktionsaufruf, bevor die ursprüngliche Funktion ausgeführt wird.

Stapeln von Dekoratoren

Dekorateure können auch gestapelt werden, was es Ihnen ermöglicht, mehrere Dekorateure auf eine einzelne Funktion anzuwenden. Hier ist ein Beispiel:

def uppercase(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

def exclaim(func):
    def wrapper():
        result = func()
        return result + "!"
    return wrapper

@exclaim
@uppercase
def say_hello():
    return "hello"

print(say_hello())  ## Output: HELLO!

In diesem Beispiel wird die say_hello-Funktion sowohl mit dem uppercase- als auch mit dem exclaim-Dekorator dekoriert. Die Dekorateure werden in der Reihenfolge angewendet, in der sie aufgeführt sind. Daher wird der uppercase-Dekorator zuerst und der exclaim-Dekorator als zweites angewendet.

Durch die Verwendung von Dekoratoren können Sie das Verhalten Ihrer Funktionen leicht ändern, ohne deren Kernfunktionalität zu verändern. Dies macht Ihren Code modularer, wiederverwendbarer und leichter wartbar.

Fortgeschrittene Dekorator-Techniken und Anwendungsfälle

Wie Sie gesehen haben, sind Dekorateure (Decorators) ein mächtiges Werkzeug zur Änderung des Funktionsverhaltens in Python. In diesem Abschnitt werden wir einige fortgeschrittenere Dekorator-Techniken und Anwendungsfälle untersuchen.

Dekorieren von Klassen

Dekorateure können auch verwendet werden, um das Verhalten von Klassen zu ändern. Hier ist ein Beispiel für einen Dekorator, der einer Klasse eine Logging-Methode hinzufügt:

def log_class_methods(cls):
    class LoggedClass(cls):
        def __getattribute__(self, attr):
            if callable(super(LoggedClass, self).__getattribute__(attr)):
                def logged_method(*args, **kwargs):
                    print(f"Calling method {attr}")
                    return super(LoggedClass, self).__getattribute__(attr)(*args, **kwargs)
                return logged_method
            return super(LoggedClass, self).__getattribute__(attr)
    return LoggedClass

@log_class_methods
class MyClass:
    def __init__(self, value):
        self.value = value

    def do_something(self):
        print(f"Doing something with value: {self.value}")

obj = MyClass(42)
obj.do_something()  ## Output: Calling method do_something
                   ## Doing something with value: 42

In diesem Beispiel nimmt der log_class_methods-Dekorator eine Klasse als Argument entgegen und gibt eine neue Klasse zurück, die alle Methoden der ursprünglichen Klasse mit einer Logging-Funktion umhüllt.

Dekorateure mit Zustand

Dekorateure können auch Zustände zwischen Funktionsaufrufen aufrechterhalten. Dies kann für Caching, Rate Limiting oder andere zustandsabhängige Operationen nützlich sein. Hier ist ein Beispiel für einen Dekorator, der die Ergebnisse einer Funktion zwischenspeichert:

def cache(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            print("Returning cached result")
            return cache[args]
        else:
            result = func(*args)
            cache[args] = result
            return result
    return wrapper

@cache
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(10))  ## Output: Calculating fibonacci(10)
                     ## 55
print(fibonacci(10))  ## Output: Returning cached result
                     ## 55

In diesem Beispiel verwaltet der cache-Dekorator ein Wörterbuch von Funktionsaufruf-Argumenten und deren entsprechenden Ergebnissen. Wenn die dekorierte Funktion aufgerufen wird, überprüft der Dekorator zunächst, ob das Ergebnis bereits zwischengespeichert ist, und wenn ja, gibt er das zwischengespeicherte Ergebnis zurück. Andernfalls berechnet er das Ergebnis und speichert es im Cache für die zukünftige Verwendung.

Dekorator-Fabriken

Manchmal möchten Sie möglicherweise Dekorateure erstellen, die mit Argumenten konfiguriert werden können. Dies kann mit einer Dekorator-Fabrik erreicht werden, die eine Funktion ist, die einen Dekorator zurückgibt. Hier ist ein Beispiel:

def repeat(n):
    def decorator(func):
        def wrapper():
            result = ""
            for _ in range(n):
                result += func()
            return result
        return wrapper
    return decorator

@repeat(3)
def say_hello():
    return "hello "

print(say_hello())  ## Output: hello hello hello

In diesem Beispiel ist die repeat-Funktion eine Dekorator-Fabrik, die ein Argument n nimmt und einen Dekorator zurückgibt, der die ursprüngliche Funktion umhüllt, sie n Mal aufruft und die Ergebnisse zusammenfügt.

Diese fortgeschrittenen Dekorator-Techniken zeigen die Flexibilität und Mächtigkeit von Dekoratoren in Python. Durch die Verwendung von Dekoratoren können Sie wiederverwendbaren, modularen und leicht wartbaren Code erstellen, der einfach erweitert und an Ihre Bedürfnisse angepasst werden kann.

Zusammenfassung

Am Ende dieses Tutorials werden Sie ein solides Verständnis von Python-Dekoratoren (Decorators) haben und wissen, wie Sie sie effektiv anwenden können, um das Verhalten von Funktionen zu ändern. Sie werden fortgeschrittene Techniken lernen und reale Anwendungsfälle untersuchen, was Ihnen ermöglicht, effizienteren, lesbareren und wartbareren Python-Code zu schreiben.