Dekoratéři jsou velmi mocným a užitečným nástrojem v Pythonu, protože umožňují programátorům upravovat chování funkce nebo třídy. Dekorátory nám umožňují zabalit další funkci, abychom rozšířili chování zabalené funkce, aniž bychom ji trvale upravovali. Než se však ponoříme hlouběji do dekoratérů, pochopme některé koncepty, které se nám při učení dekoratérů budou hodit.
Objekty první třídy
V Pythonu jsou funkce prvotřídní předměty což znamená, že funkce v Pythonu mohou být použity nebo předány jako argumenty.
Vlastnosti prvotřídních funkcí:
- Funkce je instancí typu Object.
- Funkci můžete uložit do proměnné.
- Funkci můžete předat jako parametr jiné funkci.
- Funkci můžete vrátit z funkce.
- Můžete je uložit do datových struktur, jako jsou hashovací tabulky, seznamy, …
Pro lepší pochopení zvažte níže uvedené příklady.
Příklad 1: Zacházení s funkcemi jako s objekty.
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ýstup:
HELLO HELLO>
Ve výše uvedeném příkladu jsme funkci výkřik přiřadili proměnné. To nezavolá funkci, místo toho vezme objekt funkce, na který odkazuje výkřik, a vytvoří druhé jméno, které na něj ukazuje, křičet.
Příklad 2: Předání funkce jako 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ýstup:
HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>
Ve výše uvedeném příkladu má funkce pozdrav jako parametr jinou funkci (v tomto případě křičet a šeptat). Funkce předaná jako argument se pak volá uvnitř funkce pozdrav.
Příklad 3: Vrácení funkcí z jiné funkce.
Python3
řetězec.formát
# 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ýstup:
25>
Ve výše uvedeném příkladu jsme vytvořili funkci uvnitř jiné funkce a poté jsme vrátili funkci vytvořenou uvnitř.
Výše uvedené tři příklady znázorňují důležité pojmy, které jsou potřebné k pochopení dekoratérů. Poté, co jsme je prošli, pojďme se nyní ponořit hluboko do dekoratérů.
Dekoratéři
Jak je uvedeno výše, dekorátory se používají k úpravě chování funkce nebo třídy. V dekorátorech se funkce berou jako argument jiné funkce a pak se volají uvnitř funkce wrapper.
Syntaxe pro Decorator:
@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>
Ve výše uvedeném kódu je gfg_decorator volatelná funkce, která přidá nějaký kód nad nějakou jinou volatelnou funkci, funkci hello_decorator a vrátí funkci wrapper.
Dekoratér může upravit chování :
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ýstup:
Hello, this is before function execution This is inside the function !! This is after function execution>
Podívejme se na chování výše uvedeného kódu a na to, jak krok za krokem běží, když je volána function_to_be_used.
Pojďme na další příklad, kde to snadno zjistíme doba provádění funkce pomocí dekoratéra.
Python3
java verze linux
# 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ýstup:
3628800 Total time taken in : factorial 2.0061802864074707>
Co když funkce něco vrátí nebo je funkci předán argument?
Ve všech výše uvedených příkladech funkce nevrátily nic, takže nebyl problém, ale může být potřeba vrácená hodnota.
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ýstup:
before Execution Inside the function after Execution Sum = 3>
Ve výše uvedeném příkladu si můžete všimnout velkého rozdílu v parametrech vnitřní funkce. Vnitřní funkce bere argument jako *args a **kwargs, což znamená, že lze předat n-tici pozičních argumentů nebo slovník argumentů klíčových slov libovolné délky. To z něj dělá obecný dekorátor, který může ozdobit funkci s libovolným počtem argumentů.
Řetězové dekoratérky
Jednodušeji řečeno řetězení dekorátorů znamená zdobení funkce více dekorátory.
Pří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ýstup:
400 200>
Výše uvedený příklad je podobný volání funkce jako –
decor1(decor(num)) decor(decor1(num2))>