Dekoratéri sú veľmi výkonným a užitočným nástrojom v Pythone, pretože umožňujú programátorom upravovať správanie funkcie alebo triedy. Dekorátory nám umožňujú zabaliť ďalšiu funkciu, aby sme rozšírili správanie zabalenej funkcie bez toho, aby sme ju natrvalo upravovali. Ale predtým, ako sa ponoríme hlboko do dekoratérov, pochopme niektoré koncepty, ktoré sa vám budú hodiť pri učení sa dekoratérov.
Objekty prvej triedy
V Pythone sú funkcie prvotriedne predmety čo znamená, že funkcie v Pythone možno použiť alebo odovzdať ako argumenty.
Vlastnosti prvotriednych funkcií:
- Funkcia je inštanciou typu Object.
- Funkciu môžete uložiť do premennej.
- Funkciu môžete odovzdať ako parameter inej funkcii.
- Funkciu môžete vrátiť z funkcie.
- Môžete ich uložiť do dátových štruktúr, ako sú hašovacie tabuľky, zoznamy, …
Pre lepšie pochopenie zvážte nižšie uvedené príklady.
Príklad 1: Zaobchádzanie s funkciami ako s objektmi.
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'>))> |
>
>
Výkon:
HELLO HELLO>
Vo vyššie uvedenom príklade sme premennej priradili funkciu výkrik. Toto nezavolá funkciu, namiesto toho vezme funkčný objekt, na ktorý odkazuje výkrik, a vytvorí druhé meno, ktoré naň ukazuje, výkrik.
Príklad 2: Odovzdanie funkcie ako argumentu
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)> |
>
>
Výkon:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
Vo vyššie uvedenom príklade má funkcia pozdravu inú funkciu ako parameter (v tomto prípade kričanie a šepot). Funkcia odovzdaná ako argument sa potom volá vo vnútri funkcie pozdrav.
Príklad 3: Vrátenie funkcií z inej funkcie.
Python3
java zoznamy
# 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>))> |
>
>
Výkon:
25>
Vo vyššie uvedenom príklade sme vytvorili funkciu vo vnútri inej funkcie a potom sme vrátili funkciu vytvorenú vo vnútri.
Vyššie uvedené tri príklady zobrazujú dôležité pojmy, ktoré sú potrebné na pochopenie dekoratérov. Po ich prejdení sa teraz ponorme hlboko do dekoratérov.
Dekoratéri
Ako je uvedené vyššie, dekorátory sa používajú na úpravu správania funkcie alebo triedy. V dekorátoroch sa funkcie berú ako argument inej funkcie a potom sa volajú vo funkcii wrapper.
Syntax pre Decorator:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''> Vo vyššie uvedenom kóde je gfg_decorator volateľná funkcia, ktorá pridá nejaký kód nad nejakú ďalšiu volateľnú funkciu, funkciu hello_decorator a vráti funkciu wrapper.
Dekoratér môže upraviť správanie :
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()> |
>
>
Výkon:
Hello, this is before function execution This is inside the function !! This is after function execution>
Pozrime sa, ako sa vyššie uvedený kód správa a ako prebieha krok za krokom, keď sa volá funkcia function_to_be_used.

Prejdime na ďalší príklad, kde to môžeme ľahko zistiť čas vykonania funkcie pomocou dekoratéra.
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>)> |
>
>
Výkon:
3628800 Total time taken in : factorial 2.0061802864074707>
Čo ak funkcia niečo vráti alebo sa funkcii odovzdá argument?
Vo všetkých vyššie uvedených príkladoch funkcie nevrátili nič, takže nenastal problém, ale možno budete potrebovať vrátenú hodnotu.
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))> |
>
>
Výkon:
before Execution Inside the function after Execution Sum = 3>
Vo vyššie uvedenom príklade si môžete všimnúť veľký rozdiel v parametroch vnútornej funkcie. Vnútorná funkcia berie argument ako *args a **kwargs, čo znamená, že je možné odovzdať n-ticu pozičných argumentov alebo slovník argumentov kľúčových slov ľubovoľnej dĺžky. To z neho robí všeobecný dekoratér, ktorý môže ozdobiť funkciu s ľubovoľným počtom argumentov.
Reťazové dekoratérky
Zjednodušene povedané reťazenie dekoratérov znamená zdobenie funkcie viacerými dekoratérmi.
scan.nextstring java
Príklad:
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())> |
>
>
Výkon:
400 200>
Vyššie uvedený príklad je podobný volaniu funkcie ako –
decor1(decor(num)) decor(decor1(num2))>