Un ghid pentru decoratorii Python pentru programatori avansați
Decoratorii Python sunt un instrument puternic și flexibil pentru modificarea comportamentului funcțiilor sau metodelor. Acestea permit programatorilor să extindă sau să modifice funcționalitatea obiectelor apelabile într-un mod curat, ușor de citit și de întreținut. Acest articol explorează concepte avansate legate de decoratorii Python, inclusiv decoratorii imbricați, argumentele decoratorilor și decoratorii bazați pe clasă.
Ce sunt Decoratorii?
Decoratorii sunt funcții care modifică comportamentul unei alte funcții. Ei înglobează o altă funcție pentru a-și extinde comportamentul fără a-i modifica în mod explicit codul. Decoratorii sunt definiți folosind sintaxa @decorator_name
și sunt plasați deasupra definiției funcției.
Sintaxa de bază a decoratorului
Un decorator simplu ia o funcție ca argument, definește o funcție interioară care adaugă un anumit comportament și apoi returnează funcția interioară.
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()
Decoratorul funcționează cu argumente
Decoratorii pot fi mai flexibili acceptând argumente. Pentru a crea un astfel de decorator, trebuie să scrieți o funcție care returnează un decorator. Acest lucru permite adăugarea unui comportament mai dinamic decoratorilor.
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 greet(name):
print(f"Hello, {name}!")
greet("Alice")
Decoratori de cuiburi
Decoratorii pot fi imbricați pentru a combina mai multe comportamente. De exemplu, putem folosi doi sau mai mulți decoratori pe o singură funcție.
def uppercase_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
def repeat_decorator(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result + result
return wrapper
@repeat_decorator
@uppercase_decorator
def say_word(word):
return word
print(say_word("hello"))
Decoratori de clasă
În Python, decoratorii pot fi implementați și ca clase folosind metoda __call__
. Decoratorii bazați pe clasă sunt utili atunci când aveți nevoie de un management și un comportament mai complex de stat.
class CountCalls:
def __init__(self, func):
self.func = func
self.num_calls = 0
def __call__(self, *args, **kwargs):
self.num_calls += 1
print(f"Call {self.num_calls} of {self.func.__name__!r}")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
say_hello()
say_hello()
Folosind functools.wraps
pentru a păstra metadatele
Când scrieți decoratori, funcția decorată își pierde metadatele originale, cum ar fi numele și docstring. Decoratorul functools.wraps
poate fi folosit pentru a copia metadatele funcției originale în funcția wrapper.
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("Wrapper function executed before", func.__name__)
return func(*args, **kwargs)
return wrapper
@my_decorator
def display_info(name, age):
"""Displays name and age."""
print(f"display_info ran with arguments ({name}, {age})")
print(display_info.__name__) # Output: display_info
print(display_info.__doc__) # Output: Displays name and age.
Concluzie
Decoratorii Python sunt o caracteristică puternică care permite proiectarea flexibilă a codului și modificarea comportamentului. Utilizarea avansată, cum ar fi decoratorii imbricați, decoratorii cu argumente și decoratorii bazați pe clasă, pot oferi și mai multă funcționalitate și lizibilitate programelor Python. Înțelegând și utilizând corect decoratorii, dezvoltatorii pot scrie cod mai concis, mai eficient și mai ușor de citit.