Dekoraterji so zelo zmogljivo in uporabno orodje v Pythonu, saj programerjem omogočajo spreminjanje obnašanja funkcije ali razreda. Dekoraterji nam omogočajo, da ovijemo drugo funkcijo, da razširimo vedenje ovite funkcije, ne da bi jo trajno spremenili. Toda preden se poglobimo v dekoraterje, naj razumemo nekaj konceptov, ki nam bodo prišli prav pri učenju dekoraterjev.
Prvorazredni predmeti
V Pythonu so funkcije prvovrstne predmete kar pomeni, da je mogoče funkcije v Pythonu uporabiti ali posredovati kot argumente.
Lastnosti funkcij prvega razreda:
- Funkcija je primerek tipa Object.
- Funkcijo lahko shranite v spremenljivko.
- Funkcijo lahko kot parameter posredujete drugi funkciji.
- Funkcijo lahko vrnete iz funkcije.
- Shranite jih lahko v podatkovne strukture, kot so zgoščene tabele, seznami, …
Za boljše razumevanje si oglejte spodnje primere.
Primer 1: Obravnavanje funkcij kot objektov.
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'> ))> |
>
>
Izhod:
HELLO HELLO>
V zgornjem primeru smo spremenljivki dodelili funkcijo shout. To ne bo poklicalo funkcije, namesto tega vzame funkcijski objekt, na katerega se sklicuje shout, in ustvari drugo ime, ki kaže nanj, yell.
Primer 2: Posredovanje funkcije kot argumenta
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)> |
>
>
Izhod:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
V zgornjem primeru funkcija pozdrava kot parameter sprejme drugo funkcijo (v tem primeru krik in šepet). Funkcija, posredovana kot argument, se nato kliče znotraj funkcije pozdrav.
Primer 3: Vrnitev funkcij iz druge funkcije.
Python3
java seznami
# 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> ))> |
>
>
Izhod:
25>
V zgornjem primeru smo ustvarili funkcijo znotraj druge funkcije in nato vrnili funkcijo, ustvarjeno znotraj.
Zgornji trije primeri prikazujejo pomembne koncepte, ki so potrebni za razumevanje dekoraterjev. Ko smo jih pregledali, se zdaj poglobimo v dekoraterje.
Dekoraterji
Kot je navedeno zgoraj, se dekoraterji uporabljajo za spreminjanje obnašanja funkcije ali razreda. V dekoratorjih so funkcije vzete kot argument v drugo funkcijo in nato poklicane znotraj funkcije ovoja.
Sintaksa za dekorator:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>
V zgornji kodi je gfg_decorator funkcija, ki jo je mogoče priklicati, ki bo dodala nekaj kode na vrh neke druge funkcije, ki jo je mogoče priklicati, funkcije hello_decorator, in vrnila funkcijo ovoja.
Dekorater lahko spremeni obnašanje :
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()> |
>
>
Izhod:
Hello, this is before function execution This is inside the function !! This is after function execution>
Oglejmo si obnašanje zgornje kode in kako teče korak za korakom, ko se pokliče funkcija_to_be_used.
Pojdimo na drug primer, kjer lahko zlahka ugotovimo čas izvajanja funkcije z uporabo dekoraterja.
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> )> |
>
>
Izhod:
3628800 Total time taken in : factorial 2.0061802864074707>
Kaj pa, če funkcija nekaj vrne ali je funkciji posredovan argument?
V vseh zgornjih primerih funkcije niso vrnile ničesar, tako da ni prišlo do težave, vendar boste morda potrebovali vrnjeno vrednost.
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))> |
>
>
Izhod:
before Execution Inside the function after Execution Sum = 3>
V zgornjem primeru boste morda opazili veliko razliko v parametrih notranje funkcije. Notranja funkcija sprejme argument kot *args in **kwargs, kar pomeni, da se lahko posreduje poljubna dolžina nabora pozicijskih argumentov ali slovar ključnih argumentov. Zaradi tega je splošni dekorater, ki lahko okrasi funkcijo s poljubnim številom argumentov.
Verižni okraševalci
Preprosteje povedano, veriženje dekoraterjev pomeni dekoriranje funkcije z več dekoraterji.
primer:
Python3
# 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())> |
>
>
Izhod:
mvc java
400 200>
Zgornji primer je podoben klicanju funkcije kot –
decor1(decor(num)) decor(decor1(num2))>