Utilizarea decoratorilor in Python

Utilizarea decoratorilor in Python


Decoratorii sunt una dintre cele mai puternice și elegante caracteristici ale limbajului Python. Ei permit modificarea sau extinderea comportamentului funcțiilor sau metodelor fără a schimba efectiv codul funcției. În esență, un decorator este o funcție care ia o altă funcție și o extinde sau o modifică într-un fel.

Conceptul de decorator

Funcții ca obiecte de primă clasă

În Python, funcțiile sunt obiecte de primă clasă, ceea ce înseamnă că pot fi atribuite unor variabile, pot fi returnate de alte funcții și pot fi transmise ca argumente altor funcții. Acest lucru este esențial pentru înțelegerea decoratorilor.

Funcții de nivel superior

Funcțiile de nivel superior sunt acele funcții care pot accepta alte funcții ca argumente sau care returnează alte funcții. Decoratorii sunt, de fapt, funcții de nivel superior.

Exemple de funcții ca obiecte de primă clasă

def say_hello(name):
    return f"Hello, {name}"

# Atribuirea unei funcții unei variabile
greet = say_hello
print(greet("Alice"))  # Output: Hello, Alice


Crearea unui decorator simplu

Să începem prin a crea un decorator simplu care adaugă un comportament suplimentar unei funcții.

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()


  1. Definirea decoratorului my_decorator:

    • my_decorator este o funcție care primește o funcție ca argument (func).

    • În interiorul acesteia, se definește o funcție wrapper care adaugă comportament înainte și după apelul funcției func.

    • wrapper este returnată și va înlocui funcția originală.

  2. Utilizarea decoratorului:

    • Sintaxa @my_decorator este echivalentă cu say_hello = my_decorator(say_hello).

    • Atunci când say_hello este apelată, de fapt se apelează wrapper.

Când apelăm say_hello(), output-ul va fi:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.


Decoratori cu argumente

Deseori, dorim ca decoratorii să accepte argumente. Pentru aceasta, trebuie să creăm un decorator care returnează o funcție care la rândul ei returnează un wrapper.

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 say_hello(name):
    print(f"Hello, {name}!")
say_hello("Alice")


  1. Definirea decoratorului repeat:

    • repeat este o funcție care acceptă un argument (num_times).

    • repeat returnează un decorator (decorator_repeat) care la rândul său returnează un wrapper.

  2. Utilizarea decoratorului:

    • Sintaxa @repeat(num_times=3) specifică faptul că funcția say_hello trebuie repetată de 3 ori.

Când apelăm say_hello("Alice"), output-ul va fi:

Hello, Alice!
Hello, Alice!
Hello, Alice!


Decoratori pentru metodele claselor

Decoratorii pot fi folosiți și pentru metodele claselor. Să vedem un exemplu:

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

class MyClass:

    @log_method_call
    def greet(self, name):
        print(f"Hello, {name}!")

obj = MyClass()
obj.greet("Bob")


  1. Definirea decoratorului log_method_call:

    • log_method_call este o funcție care acceptă o funcție (func) și returnează un wrapper.

    • wrapper primește self, *args, și **kwargs pentru a suporta metodele claselor.

  2. Utilizarea decoratorului:

    • Sintaxa @log_method_call aplicată metodei greet din MyClass.

Când apelăm obj.greet("Bob"), output-ul va fi:

Calling method greet
Hello, Bob!


Decoratori din bibliotecile standard

Python include câțiva decoratori utili în bibliotecile sale standard, cum ar fi @staticmethod, @classmethod, și @property.

class MyClass:

    @staticmethod
    def static_method():
        print("This is a static method.")

    @classmethod
    def class_method(cls):
        print(f"This is a class method. Class: {cls.__name__}")

MyClass.static_method()
MyClass.class_method()


  1. @staticmethod:

    • Definește o metodă care nu primește implicit un argument self sau cls. Este folosită atunci când metoda nu are nevoie de acces la instanță sau clasă.
  2. @classmethod:

    • Definește o metodă care primește implicit un argument cls care reprezintă clasa. Este folosită atunci când metoda trebuie să acceseze atributele sau metodele clasei.

Când apelăm metodele, output-ul va fi:

This is a static method.
This is a class method. Class: MyClass


Decoratorii sunt o caracteristică esențială a limbajului Python, oferind o modalitate elegantă de a extinde și modifica comportamentul funcțiilor și metodelor. Prin înțelegerea și utilizarea corectă a decoratorilor, putem scrie cod mai curat, mai modular și mai ușor de întreținut.


Trebuie să fii autentificat pentru a accesa editorul de cod și pentru a experimenta codul prezentat în acest tutorial.

Intră în cont