logo

Decoratori în Python

Decoratori sunt un instrument foarte puternic și util în Python, deoarece le permite programatorilor să modifice comportamentul unei funcții sau clase. Decoratorii ne permit să împachetăm o altă funcție pentru a extinde comportamentul funcției de împachetat, fără a o modifica permanent. Dar înainte de a ne aprofunda în decoratori, să înțelegem câteva concepte care ne vor fi utile în învățarea decoratorilor.

Obiecte de primă clasă
În Python, funcțiile sunt obiecte de primă clasă ceea ce înseamnă că funcțiile din Python pot fi folosite sau transmise ca argumente.
Proprietăți ale funcțiilor de primă clasă:

  • O funcție este o instanță a tipului Object.
  • Puteți stoca funcția într-o variabilă.
  • Puteți trece funcția ca parametru unei alte funcții.
  • Puteți returna funcția dintr-o funcție.
  • Le puteți stoca în structuri de date precum tabele hash, liste, ...

Luați în considerare exemplele de mai jos pentru o mai bună înțelegere.



Exemplul 1: Tratarea funcțiilor ca obiecte.

Python3








# Python program to illustrate functions> # can be treated as objects> def> shout(text):> >return> text.upper()> print>(shout(>'Hello'>))> yell>=> shout> print>(yell(>'Hello'>))>

>

>

Ieșire:

HELLO HELLO>

În exemplul de mai sus, am atribuit funcția shout unei variabile. Acest lucru nu va apela funcția, ci ia obiectul funcție la care se face referire printr-un strigăt și creează un al doilea nume care indică spre el, țipă.

Exemplul 2: Transmiterea funcției ca argument

Python3




# Python program to illustrate functions> # can be passed as arguments to other functions> def> shout(text):> >return> text.upper()> def> whisper(text):> >return> text.lower()> def> greet(func):> ># storing the function in a variable> >greeting>=> func(>'''Hi, I am created by a function passed as an argument.'''>)> >print> (greeting)> greet(shout)> greet(whisper)>

>

>

Ieșire:

HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>

În exemplul de mai sus, funcția de salut ia ca parametru o altă funcție (strigă și șoaptă în acest caz). Funcția transmisă ca argument este apoi apelată în interiorul funcției greet.

Exemplul 3: Revenirea funcțiilor dintr-o altă funcție.

Python3




arhitectura de retea
# Python program to illustrate functions> # Functions can return another function> def> create_adder(x):> >def> adder(y):> >return> x>+>y> >return> adder> add_15>=> create_adder(>15>)> print>(add_15(>10>))>

>

>

Ieșire:

25>

În exemplul de mai sus, am creat o funcție în interiorul unei alte funcții și apoi am returnat funcția creată în interior.
Cele trei exemple de mai sus descriu conceptele importante care sunt necesare pentru a înțelege decoratorii. După ce le-am parcurs, haideți să ne aprofundăm acum în decoratori.

Decoratori

După cum sa menționat mai sus, decoratorii sunt utilizați pentru a modifica comportamentul funcției sau clasei. În Decorators, funcțiile sunt luate ca argument într-o altă funcție și apoi apelate în interiorul funcției wrapper.

Sintaxă pentru Decorator:

@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>

În codul de mai sus, gfg_decorator este o funcție apelabilă, care va adăuga un cod în partea de sus a unei alte funcții apelabile, funcția hello_decorator și va returna funcția wrapper.

Decoratorul poate modifica comportament :

Python3




# defining a decorator> def> hello_decorator(func):> ># inner1 is a Wrapper function in> ># which the argument is called> > ># inner function can access the outer local> ># functions like in this case 'func'> >def> inner1():> >print>(>'Hello, this is before function execution'>)> ># calling the actual function now> ># inside the wrapper function.> >func()> >print>(>'This is after function execution'>)> > >return> inner1> # defining a function, to be called inside wrapper> def> function_to_be_used():> >print>(>'This is inside the function !!'>)> # passing 'function_to_be_used' inside the> # decorator to control its behaviour> function_to_be_used>=> hello_decorator(function_to_be_used)> # calling the function> function_to_be_used()>

>

>

Ieșire:

Hello, this is before function execution This is inside the function !! This is after function execution>

Să vedem comportamentul codului de mai sus și cum rulează pas cu pas atunci când funcția_to_be_used este apelată.

Să trecem la un alt exemplu de unde putem afla cu ușurință timpul de execuție al unei funcții folosind un decorator.

Python3




# importing libraries> import> time> import> math> # decorator to calculate duration> # taken by any function.> def> calculate_time(func):> > ># added arguments inside the inner1,> ># if function takes any arguments,> ># can be added like this.> >def> inner1(>*>args,>*>*>kwargs):> ># storing time before function execution> >begin>=> time.time()> > >func(>*>args,>*>*>kwargs)> ># storing time after function execution> >end>=> time.time()> >print>(>'Total time taken in : '>, func.__name__, end>-> begin)> >return> inner1> # this can be added to any function present,> # in this case to calculate a factorial> @calculate_time> def> factorial(num):> ># sleep 2 seconds because it takes very less time> ># so that you can see the actual difference> >time.sleep(>2>)> >print>(math.factorial(num))> # calling the function.> factorial(>10>)>

>

>

Ieșire:

3628800 Total time taken in : factorial 2.0061802864074707>

Ce se întâmplă dacă o funcție returnează ceva sau un argument este transmis funcției?

În toate exemplele de mai sus, funcțiile nu au returnat nimic, așa că nu a existat o problemă, dar poate fi nevoie de valoarea returnată.

Python3




def> hello_decorator(func):> >def> inner1(>*>args,>*>*>kwargs):> > >print>(>'before Execution'>)> > ># getting the returned value> >returned_value>=> func(>*>args,>*>*>kwargs)> >print>(>'after Execution'>)> > ># returning the value to the original frame> >return> returned_value> > >return> inner1> # adding decorator to the function> @hello_decorator> def> sum_two_numbers(a, b):> >print>(>'Inside the function'>)> >return> a>+> b> a, b>=> 1>,>2> # getting the value through return of the function> print>(>'Sum ='>, sum_two_numbers(a, b))>

>

>

Ieșire:

before Execution Inside the function after Execution Sum = 3>

În exemplul de mai sus, este posibil să observați o diferență semnificativă între parametrii funcției interne. Funcția interioară ia argumentul ca *args și **kwargs, ceea ce înseamnă că un tuplu de argumente poziționale sau un dicționar de argumente de cuvinte cheie poate fi transmis de orice lungime. Acest lucru îl face un decorator general care poate decora o funcție având orice număr de argumente.

Înlănțuirea decoratorilor

În termeni mai simpli, înlănțuirea decoratorilor înseamnă decorarea unei funcții cu mai mulți decoratori.

Exemplu:

Python3


cum se apelează o metodă în java



# code for testing decorator chaining> def> decor1(func):> >def> inner():> >x>=> func()> >return> x>*> x> >return> inner> def> decor(func):> >def> inner():> >x>=> func()> >return> 2> *> x> >return> inner> @decor1> @decor> def> num():> >return> 10> @decor> @decor1> def> num2():> >return> 10> > print>(num())> print>(num2())>

>

>

Ieșire:

400 200>

Exemplul de mai sus este similar cu apelarea funcției ca –

decor1(decor(num)) decor(decor1(num2))>