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()
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țieifunc
.wrapper
este returnată și va înlocui funcția originală.
Utilizarea decoratorului:
Sintaxa
@my_decorator
este echivalentă cusay_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")
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ă unwrapper
.
Utilizarea decoratorului:
- Sintaxa
@repeat(num_times=3)
specifică faptul că funcțiasay_hello
trebuie repetată de 3 ori.
- Sintaxa
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")
Definirea decoratorului
log_method_call
:log_method_call
este o funcție care acceptă o funcție (func
) și returnează unwrapper
.wrapper
primeșteself
,*args
, și**kwargs
pentru a suporta metodele claselor.
Utilizarea decoratorului:
- Sintaxa
@log_method_call
aplicată metodeigreet
dinMyClass
.
- Sintaxa
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()
@staticmethod
:- Definește o metodă care nu primește implicit un argument
self
saucls
. Este folosită atunci când metoda nu are nevoie de acces la instanță sau clasă.
- Definește o metodă care nu primește implicit un argument
@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.
- Definește o metodă care primește implicit un argument
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.