Dekoratori ir ļoti spēcīgs un noderīgs Python rīks, jo tas ļauj programmētājiem mainīt funkcijas vai klases uzvedību. Dekoratori ļauj mums ietīt citu funkciju, lai paplašinātu iesaiņotās funkcijas darbību, to neatgriezeniski nemainot. Bet pirms dziļi iedziļināties dekoratoros, ļaujiet mums saprast dažus jēdzienus, kas noderēs dekoratoru apguvē.
Pirmās klases objekti
Pythonā funkcijas ir pirmās klases objekti kas nozīmē, ka Python funkcijas var izmantot vai nodot kā argumentus.
Pirmās klases funkciju īpašības:
- Funkcija ir objekta tipa gadījums.
- Varat saglabāt funkciju mainīgajā.
- Varat nodot funkciju kā parametru citai funkcijai.
- Varat atgriezt funkciju no funkcijas.
- Varat tos saglabāt datu struktūrās, piemēram, jaucēj tabulās, sarakstos,…
Apsveriet tālāk sniegtos piemērus, lai labāk izprastu.
1. piemērs: Funkcijas traktēšana kā objektus.
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'> ))> |
>
>
Izvade:
HELLO HELLO>
Iepriekš minētajā piemērā mēs esam piešķīruši funkciju kliegt mainīgajam. Tas neizsauks funkciju, tā vietā tiek izmantots funkcijas objekts, uz kuru atsaucas kliedziens, un tiek izveidots otrs nosaukums, kas norāda uz to, kliedziens.
2. piemērs: Funkcijas nodošana kā arguments
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)> |
>
>
Izvade:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
Iepriekš minētajā piemērā sveiciena funkcija kā parametrs izmanto citu funkciju (šajā gadījumā kliedz un čuksti). Funkcija, kas nodota kā arguments, tiek izsaukta funkcijas sveicināt iekšpusē.
3. piemērs: Funkciju atgriešana no citas funkcijas.
Python3
java datu struktūras
# 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> ))> |
>
>
Izvade:
25>
Iepriekš minētajā piemērā mēs esam izveidojuši funkciju citas funkcijas iekšpusē un pēc tam atgriezuši tajā izveidoto funkciju.
Iepriekš minētie trīs piemēri attēlo svarīgos jēdzienus, kas nepieciešami dekoratoru izpratnei. Pēc tam, kad tie ir izgājuši cauri, iedziļināmies dekoratoros.
Dekoratori
Kā minēts iepriekš, dekoratorus izmanto, lai mainītu funkcijas vai klases uzvedību. Programmā Dekoratori funkcijas tiek pieņemtas kā arguments citā funkcijā un pēc tam tiek izsauktas iesaiņojuma funkcijā.
Dekoratora sintakse:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>
Iepriekš minētajā kodā gfg_decorator ir izsaucama funkcija, kas pievienos kodu kādai citai izsaucamajai funkcijai hello_decorator un atgriezīs iesaiņojuma funkciju.
Dekorators var modificēt uzvedība :
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()> |
>
>
Izvade:
Hello, this is before function execution This is inside the function !! This is after function execution>
Apskatīsim iepriekš minētā koda darbību un to, kā tas darbojas soli pa solim, kad tiek izsaukta funkcija_to_be_used.
Pāriesim pie cita piemēra, kur mēs to varam viegli uzzināt funkcijas izpildes laiks izmantojot dekoratoru.
Python3
css necaurredzamības pāreja
# 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> )> |
>
>
Izvade:
3628800 Total time taken in : factorial 2.0061802864074707>
Ko darīt, ja funkcija kaut ko atgriež vai funkcijai tiek nodots arguments?
Visos iepriekš minētajos piemēros funkcijas neko neatgrieza, tāpēc problēmu nebija, taču var būt nepieciešama atgrieztā vērtība.
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))> |
>
>
Izvade:
before Execution Inside the function after Execution Sum = 3>
Iepriekš minētajā piemērā jūs varat pamanīt ievērojamas atšķirības iekšējās funkcijas parametros. Iekšējā funkcija izmanto argumentu kā *args un **kwargs, kas nozīmē, ka pozicionālo argumentu kopa vai atslēgvārdu argumentu vārdnīca var tikt nodota jebkura garuma. Tas padara to par vispārīgu dekoratoru, kas var izrotāt funkciju ar jebkādu argumentu skaitu.
Ķēdes dekoratori
Vienkāršāk sakot, dekoratoru ķēdēšana nozīmē funkcijas dekorēšanu ar vairākiem dekoratoriem.
Piemērs:
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())> |
>
>
Izvade:
400 200>
Iepriekš minētais piemērs ir līdzīgs funkcijas izsaukšanai kā -
decor1(decor(num)) decor(decor1(num2))>