Ce face functools.wraps() și update_wrapper()
Un decorator înlocuiește funcția cu o altă funcție (învelișul). Fără măsuri speciale, funcția decorată pierde numele, documentația și semnătura originalului, ceea ce încurcă depanarea și help().
@wraps(f), pus pe funcția înveliș, copiază __name__, __doc__, __module__ și altele, și adaugă __wrapped__ cu funcția originală. update_wrapper(invelis, f) este forma ca funcție, folosită mai ales pentru clase-decorator.
Parametri
| Parametru | Descriere |
|---|---|
wrapped |
Funcția originală. |
assigned, updated |
Opțional. Atributele copiate sau actualizate. |
Ce returnează
Un decorator (wraps) sau învelișul actualizat (update_wrapper).
Exemple
Exemplul 1: Decorator care măsoară apelurile
from functools import wraps, update_wrapper
def numara_apeluri(f):
@wraps(f)
def invelis(*args, **kwargs):
invelis.apeluri += 1
return f(*args, **kwargs)
invelis.apeluri = 0
return invelis
@numara_apeluri
def salut(nume):
"""Returnează un salut."""
return f"Salut, {nume}!"
print(salut("Ana"), salut("Dan"))
print(salut.__name__, salut.__doc__, salut.apeluri)
print(salut.__wrapped__("Ioana"))
class Jurnal:
def __init__(self, f):
update_wrapper(self, f)
self.f = f
def __call__(self, *a):
print("apel", self.__name__, a)
return self.f(*a)
@Jurnal
def aduna(a, b):
return a + b
print(aduna(2, 3))
Rezultat
Salut, Ana! Salut, Dan!
salut Returnează un salut. 2
Salut, Ioana!
apel aduna (2, 3)
5
Greșeli frecvente
- Scrii un decorator fără
@wrapsși toate funcțiile decorate apar în erori și înhelp()cu numeleinvelis.
Comenzi înrudite
def: Definește o funcție: un bloc de cod cu nume, pe care îl poți apela de oricâte ori.functools.lru_cache() și functools.cache(): Memorează rezultatele unei funcții, ca apelurile repetate cu aceleași argumente să fie instantanee.help(): Afișează documentația unei funcții, clase sau modul.