Dekoratoriai yra labai galingas ir naudingas Python įrankis, nes jis leidžia programuotojams keisti funkcijos ar klasės elgesį. Dekoratoriai leidžia apvynioti kitą funkciją, kad būtų išplėsta įvyniotos funkcijos veikimas, jos visam laikui nekeičiant. Tačiau prieš gilindamiesi į dekoratorius, supraskime kai kurias sąvokas, kurios pravers mokantis dekoratorių.
Pirmos klasės objektai
Python, funkcijos yra pirmos klasės objektai o tai reiškia, kad Python funkcijos gali būti naudojamos arba perduodamos kaip argumentai.
Pirmos klasės funkcijų savybės:
- Funkcija yra objekto tipo egzempliorius.
- Funkciją galite išsaugoti kintamajame.
- Galite perduoti funkciją kaip parametrą kitai funkcijai.
- Galite grąžinti funkciją iš funkcijos.
- Galite saugoti juos duomenų struktūrose, tokiose kaip maišos lentelės, sąrašai, ...
Apsvarstykite toliau pateiktus pavyzdžius, kad geriau suprastumėte.
1 pavyzdys: Funkcijų traktavimas kaip objektai.
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'>))> |
>
>
Išvestis:
HELLO HELLO>
Aukščiau pateiktame pavyzdyje funkciją šaukti priskyrėme kintamajam. Tai neiškvies funkcijos, o paima funkcijos objektą, nurodytą šaukimu, ir sukuria antrą į jį nurodantį pavadinimą – šauksmą.
2 pavyzdys: Funkcijos perdavimas kaip argumentas
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)> |
>
>
Išvestis:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
Aukščiau pateiktame pavyzdyje pasisveikinimo funkcija naudoja kitą funkciją kaip parametrą (šiuo atveju šaukia ir šnabžda). Funkcija, perduodama kaip argumentas, iškviečiama sveikinimo funkcijos viduje.
3 pavyzdys: Funkcijų grąžinimas iš kitos funkcijos.
Python3
int į eilutę c++
# 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>))> |
>
>
Išvestis:
25>
Aukščiau pateiktame pavyzdyje sukūrėme funkciją kitos funkcijos viduje ir grąžinome viduje sukurtą funkciją.
Pirmiau pateikti trys pavyzdžiai vaizduoja svarbias sąvokas, kurių reikia norint suprasti dekoratorius. Perėję juos, pasinerkime į dekoratorius.
Dekoratoriai
Kaip minėta aukščiau, dekoratoriai naudojami funkcijos ar klasės elgsenai modifikuoti. Dekoratoriuose funkcijos paimamos kaip argumentas į kitą funkciją ir tada iškviečiamos įvyniojimo funkcijos viduje.
Dekoratoriaus sintaksė:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''> Aukščiau pateiktame kode gfg_decorator yra iškviečiama funkcija, kuri pridės kodą prie kitos iškviečiamos funkcijos, funkcijos hello_decorator, ir grąžins įvyniojimo funkciją.
Dekoratorius gali modifikuoti elgesį :
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()> |
>
strep c
>
Išvestis:
Hello, this is before function execution This is inside the function !! This is after function execution>
Pažiūrėkime, kaip veikia aukščiau pateiktas kodas ir kaip jis veikia žingsnis po žingsnio, kai iškviečiama funkcija_to_be_used.

Pereikime prie kito pavyzdžio, kur galime lengvai sužinoti funkcijos vykdymo laikas naudojant dekoratorių.
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>)> |
>
>
Išvestis:
3628800 Total time taken in : factorial 2.0061802864074707>
Ką daryti, jei funkcija kažką grąžina arba funkcijai perduodamas argumentas?
Visuose aukščiau pateiktuose pavyzdžiuose funkcijos nieko negrąžino, todėl problemų nekilo, tačiau gali prireikti grąžintos vertės.
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))> |
>
>
Išvestis:
before Execution Inside the function after Execution Sum = 3>
Aukščiau pateiktame pavyzdyje galite pastebėti didelį vidinės funkcijos parametrų skirtumą. Vidinė funkcija priima argumentą kaip *args ir **kwargs, o tai reiškia, kad galima perduoti bet kokio ilgio pozicijos argumentų rinkinį arba raktinių žodžių argumentų žodyną. Dėl to jis yra bendras dekoratorius, galintis papuošti funkciją, turinčią bet kokį argumentų skaičių.
Grandininiai dekoratoriai
Paprasčiau tariant, dekoratorių sujungimas grandinėmis reiškia funkcijos dekoravimą keliais dekoratoriais.
Pavyzdys:
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())> |
>
>
Išvestis:
400 200>
Aukščiau pateiktas pavyzdys yra panašus į funkcijos iškvietimą kaip -
decor1(decor(num)) decor(decor1(num2))>