Sådan bruger du Python-dekoratorer til at forbedre funktioner

Python dekoratorer er en kraftfuld og fleksibel måde at ændre eller forbedre funktioner og metoder på. Dekoratorer giver en måde at indpakke en funktion med yderligere funktionalitet, så du kan udvide dens adfærd uden at ændre dens faktiske kode. Denne artikel vil introducere dig til begrebet dekoratører, hvordan man skaber og bruger dem, og udforske nogle praktiske eksempler.

Hvad er en dekoratør?

En dekoratør er en funktion, der tager en anden funktion og udvider sin adfærd uden eksplicit at ændre den. I Python bruges dekoratører ofte til at tilføje funktionalitet såsom logning, adgangskontrol eller ydeevnemåling til eksisterende funktioner eller metoder. Dekoratorer anvendes på funktioner ved hjælp af syntaksen @decorator_name.

# Basic example of a decorator
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()

Sådan fungerer dekoratører

Når du anvender en dekoratør på en funktion, udfører Python i det væsentlige følgende trin:

  1. Dekoratorfunktionen kaldes med den oprindelige funktion som argument.
  2. Dekorationsfunktionen definerer en ny funktion (ofte kaldet wrapper), der forbedrer eller ændrer den oprindelige funktions opførsel.
  3. Dekorationsfunktionen returnerer den nye funktion.
  4. Når den dekorerede funktion kaldes, kalder den faktisk den nye funktion returneret af dekoratøren.

Oprettelse af en simpel dekoratør

Lad os skabe en simpel dekoratør, der måler udførelsestiden for en funktion. Dette er nyttigt til præstationstest og optimering.

import time

def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Execution time: {end_time - start_time} seconds")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(2)
    print("Function finished!")

slow_function()

Brug af dekoratører med argumenter

Nogle gange vil du måske videregive argumenter til din dekoratør. For at opnå dette skal du oprette en dekoratørfabrik - en funktion, der returnerer en dekoratør. Her er et eksempel på en dekoratør, der tager et argument for at angive en brugerdefineret besked.

def custom_message_decorator(message):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(message)
            return func(*args, **kwargs)
        return wrapper
    return decorator

@custom_message_decorator("Starting the function...")
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Dekoratører til metoder i klasser

Dekoratører kan også bruges med metoder inden for klasser. Almindelige anvendelser omfatter logningsmetodekald, adgangskontrol og cache-resultater. Her er et eksempel på brug af en dekorator til at logge metodekald i en klasse.

def log_method_call(method):
    def wrapper(self, *args, **kwargs):
        print(f"Calling {method.__name__} with arguments {args} and keyword arguments {kwargs}")
        return method(self, *args, **kwargs)
    return wrapper

class MyClass:
    @log_method_call
    def my_method(self, x, y):
        print(f"Result: {x + y}")

obj = MyClass()
obj.my_method(5, 7)

Kæde dekoratører

Du kan anvende flere dekoratører til en enkelt funktion. De påføres fra den inderste dekoratør til den yderste. Dette giver dig mulighed for at sammensætte forskellige funktionaliteter. Her er et eksempel på at sammenkæde to dekoratører:

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result.upper()
    return wrapper

def exclamation_decorator(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return result + "!"
    return wrapper

@exclamation_decorator
@uppercase_decorator
def greet(name):
    return f"Hello, {name}"

print(greet("Alice"))

Konklusion

Dekoratorer er et alsidigt værktøj i Python, der giver dig mulighed for at forbedre eller ændre funktioner og metoders adfærd. Ved at bruge dekoratorer kan du tilføje genanvendelig funktionalitet på tværs af din kodebase uden at ændre kernelogikken i dine funktioner. Uanset om det er til logning, timing eller ændring af output, hjælper dekoratører med at holde din kode ren og vedligeholdelig. Øv dig i at bruge dekoratører for at blive dygtigere og udnytte deres magt i dine Python-projekter.