logo

Декоратори в Python

Декоратори є дуже потужним і корисним інструментом у Python, оскільки він дозволяє програмістам змінювати поведінку функції чи класу. Декоратори дозволяють нам обернути іншу функцію, щоб розширити поведінку загорнутої функції, не змінюючи її постійно. Але перш ніж заглибитися в декоратори, давайте розберемося з деякими поняттями, які стануть у нагоді під час вивчення декораторів.

Об'єкти першого класу
У Python функції є першокласні об'єкти це означає, що функції в Python можна використовувати або передавати як аргументи.
Властивості функцій першого класу:

  • Функція є екземпляром типу Object.
  • Ви можете зберегти функцію в змінній.
  • Ви можете передати функцію як параметр іншій функції.
  • Ви можете повернути функцію з функції.
  • Ви можете зберігати їх у структурах даних, таких як хеш-таблиці, списки тощо.

Для кращого розуміння розгляньте наведені нижче приклади.



приклад 1: Трактування функцій як об’єктів.

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'>))>

>

>

Вихід:

HELLO HELLO>

У наведеному вище прикладі ми призначили функцію shout змінній. Це не призведе до виклику функції, замість цього він бере об’єкт функції, на який посилається shout, і створює друге ім’я, що вказує на нього, yell.

приклад 2: Передача функції як аргументу

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)>

>

>

Вихід:

HI, I AM CREATED BY A FUNCTION PASSED AS AN ARGUMENT. hi, i am created by a function passed as an argument.>

У наведеному вище прикладі функція greet приймає іншу функцію як параметр (у цьому випадку крик і шепіт). Функція, передана як аргумент, викликається всередині функції greet.

приклад 3: Повернення функцій з іншої функції.

Python3




тестування на сумісність
# 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>))>

>

>

Вихід:

25>

У наведеному вище прикладі ми створили функцію всередині іншої функції, а потім повернули функцію, створену всередині.
Наведені вище три приклади описують важливі поняття, необхідні для розуміння декораторів. Ознайомившись з ними, давайте тепер заглибимося в декоратори.

Декоратори

Як зазначено вище, декоратори використовуються для зміни поведінки функції або класу. У декораторах функції беруться як аргумент в іншу функцію, а потім викликаються всередині функції-огортки.

Синтаксис для декоратора:

@gfg_decorator def hello_decorator(): print('Gfg') '''Above code is equivalent to - def hello_decorator(): print('Gfg') hello_decorator = gfg_decorator(hello_decorator)'''>

У наведеному вище коді gfg_decorator є викликаною функцією, яка додасть деякий код поверх іншої викликаної функції, функції hello_decorator, і поверне функцію-огортку.

Декоратор може змінити поведінка :

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()>

>

>

Вихід:

Hello, this is before function execution This is inside the function !! This is after function execution>

Давайте подивимося на поведінку наведеного вище коду та як він виконується крок за кроком, коли викликається function_to_be_used.

Давайте перейдемо до іншого прикладу, де ми можемо легко дізнатися час виконання функції за допомогою декоратора.

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>)>

>

>

Вихід:

3628800 Total time taken in : factorial 2.0061802864074707>

Що робити, якщо функція щось повертає або їй передається аргумент?

У всіх наведених вище прикладах функції нічого не повернули, тому проблеми не було, але може знадобитися повернуте значення.

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))>

оператор if-else java
>

>

Вихід:

before Execution Inside the function after Execution Sum = 3>

У наведеному вище прикладі ви можете помітити значну різницю в параметрах внутрішньої функції. Внутрішня функція приймає аргумент як *args і **kwargs, що означає, що можна передати кортеж позиційних аргументів або словник ключових аргументів будь-якої довжини. Це робить його загальним декоратором, який може прикрасити функцію, що має будь-яку кількість аргументів.

Ланцюгові декоратори

Простіше кажучи, ланцюжок декораторів означає декорування функції кількома декораторами.

приклад:

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())>

>

>

Вихід:

400 200>

Наведений вище приклад схожий на виклик функції як –

decor1(decor(num)) decor(decor1(num2))>