Els decoradors en Python són una característica poderosa que permet modificar el comportament de funcions o mètodes de manera elegant i reutilitzable. Són una forma de "meta-programació", ja que permeten definir funcions que poden modificar altres funcions.

Continguts

Què és un Decorador?

Un decorador és una funció que pren una altra funció com a argument i retorna una nova funció amb funcionalitat afegida. Els decoradors són molt útils per afegir comportaments comuns a múltiples funcions sense duplicar codi.

Sintaxi dels Decoradors

La sintaxi bàsica d'un decorador és la següent:

@decorator_function
def target_function():
    pass

Això és equivalent a:

def target_function():
    pass

target_function = decorator_function(target_function)

Decoradors Simples

Vegem un exemple senzill d'un decorador que imprimeix un missatge abans i després de l'execució d'una funció.

def simple_decorator(func):
    def wrapper():
        print("Abans de la funció")
        func()
        print("Després de la funció")
    return wrapper

@simple_decorator
def say_hello():
    print("Hola!")

say_hello()

Explicació del Codi

  1. simple_decorator és el decorador que pren una funció func com a argument.
  2. wrapper és la funció interna que afegeix funcionalitat abans i després de cridar func.
  3. @simple_decorator aplica el decorador a la funció say_hello.

Decoradors amb Arguments

Els decoradors també poden acceptar arguments. Per fer-ho, cal definir una funció que retorni el decorador.

def decorator_with_args(arg1, arg2):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(f"Arguments del decorador: {arg1}, {arg2}")
            return func(*args, **kwargs)
        return wrapper
    return decorator

@decorator_with_args("Hola", "Món")
def greet(name):
    print(f"Hola, {name}!")

greet("Python")

Explicació del Codi

  1. decorator_with_args és una funció que pren arguments i retorna un decorador.
  2. decorator és el decorador que pren la funció func com a argument.
  3. wrapper és la funció interna que afegeix funcionalitat abans de cridar func.

Decoradors Multiples

És possible aplicar múltiples decoradors a una sola funció. Els decoradors s'apliquen de dalt a baix.

def decorator1(func):
    def wrapper():
        print("Decorador 1")
        func()
    return wrapper

def decorator2(func):
    def wrapper():
        print("Decorador 2")
        func()
    return wrapper

@decorator1
@decorator2
def say_hello():
    print("Hola!")

say_hello()

Explicació del Codi

  1. @decorator2 s'aplica primer a say_hello.
  2. @decorator1 s'aplica després a la funció resultant de @decorator2.

Decoradors de Classe

Els decoradors també poden ser aplicats a mètodes dins de classes.

def method_decorator(func):
    def wrapper(self, *args, **kwargs):
        print("Abans del mètode")
        result = func(self, *args, **kwargs)
        print("Després del mètode")
        return result
    return wrapper

class MyClass:
    @method_decorator
    def display(self):
        print("Mètode de la classe")

obj = MyClass()
obj.display()

Explicació del Codi

  1. method_decorator és un decorador que pren un mètode de classe func com a argument.
  2. wrapper afegeix funcionalitat abans i després de cridar func.

Exercicis Pràctics

Exercici 1: Decorador de Temps d'Execució

Crea un decorador que mesuri el temps d'execució d'una funció.

import time

def time_decorator(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Temps d'execució: {end_time - start_time} segons")
        return result
    return wrapper

@time_decorator
def slow_function():
    time.sleep(2)
    print("Funció lenta")

slow_function()

Exercici 2: Decorador de Comptador de Crides

Crea un decorador que compti el nombre de vegades que una funció és cridada.

def call_counter(func):
    def wrapper(*args, **kwargs):
        wrapper.calls += 1
        print(f"Crides: {wrapper.calls}")
        return func(*args, **kwargs)
    wrapper.calls = 0
    return wrapper

@call_counter
def greet(name):
    print(f"Hola, {name}!")

greet("Python")
greet("World")

Conclusió

Els decoradors són una eina poderosa en Python que permeten modificar el comportament de funcions i mètodes de manera elegant i reutilitzable. Hem vist com crear decoradors simples, amb arguments, múltiples decoradors i decoradors de classe. També hem practicat amb alguns exercicis per reforçar els conceptes apresos.

En el següent tema, explorarem els generadors, una altra característica avançada de Python que permet treballar amb seqüències de dades de manera eficient.

Curs de Programació en Python

Mòdul 1: Introducció a Python

Mòdul 2: Estructures de Control

Mòdul 3: Funcions i Mòduls

Mòdul 4: Estructures de Dades

Mòdul 5: Programació Orientada a Objectes

Mòdul 6: Gestió de Fitxers

Mòdul 7: Gestió d'Errors i Excepcions

Mòdul 8: Temes Avançats

Mòdul 9: Proves i Depuració

Mòdul 10: Desenvolupament Web amb Python

Mòdul 11: Ciència de Dades amb Python

Mòdul 12: Projecte Final

© Copyright 2024. Tots els drets reservats