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

 10983

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

Що потрібно знати перед вивченням декораторів в Python?

Перш ніж ми поговоримо про декоратори, нам необхідно засвоїти кілька важливих понять, пов’язаних з функціями в Python. Також слід пам’ятати, що все в Python є об’єктом, навіть функції є об’єктами.

Вкладені функції

Ми можемо розмістити одну функцію всередині іншої — це називається вкладеною функцією. Наприклад:

Результат:

11

Тут ми створили функцію inner() всередині функції outer().

Передача функції як аргумент

В Python ми можемо передавати функцію як аргумент іншій функції. Наприклад:

Результат:

10

Під час виклику функції calculate() ми передаємо функцію add() як аргумент. У функції calculate() аргументи: func, x і y перетворюються на add, 4 та 6 відповідно.

Повернення функції у вигляді значення

В Python ми також можемо повернути функцію у вигляді значення. Наприклад:

Результат:

Hello, Atlantis!

Оператор return повертає внутрішню функцію hello(). Ця функція присвоюється змінній greet під час виклику зовнішньої функції greeting().

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

Декоратор — це функція, яка приймає іншу функцію та повертає її модифіковану версію.

Примітка: Фактично, будь-який об’єкт, який реалізує спеціальний метод __call__(), називається викликаючим об’єктом. Таким чином, декоратор — це викликаючий об’єкт, який повертає викликаючий об’єкт.

Наприклад:

Результат:

I am ordinary

Тут ми створили дві функції:

   функція ordinary(), яка виводить I am ordinary;

   функція make_pretty(), яка приймає як аргумент функцію, має вкладену функцію inner() та повертає її.

Ми викликаємо функцію ordinary() звичайним способом, тому отримуємо на виході I am ordinary. Тепер викличемо її за допомогою функції-декоратора:

Результат:

I got decorated
I am ordinary

Тут функція make_pretty() є декоратором. Зверніть увагу на наступний рядок коду:

Ми передаємо функцію ordinary() як аргумент функції make_pretty(). Функція make_pretty() повертає внутрішню функцію inner(), яка присвоюється змінній decorated_func.

У наступному рядку коду ми фактично викликаємо функцію inner():

Символ @ з декоратором

Замість того, щоб присвоювати виклик функції змінній, Python пропонує більш елегантний спосіб зробити те саме за допомогою символу @. Наприклад:

Результат:

I got decorated
I am ordinary

Тут функція ordinary() пов’язана з декоратором make_pretty() через використання синтаксису @make_pretty, що еквівалентно стейтменту ordinary = make_pretty(ordinary).

Декоратори та Функції з параметрами

Вищенаведений декоратор простий і працює тільки з функціями, що не мають параметрів. А якби у нас були функції, що приймають параметри, наприклад:

Ця функція має два параметри: a та b. Ми знаємо, що вона видасть помилку, якщо ми вкажемо в якості аргументу (b) значення 0.

Тепер зробимо декоратор для перевірки випадку, який може призвести до помилки (ділення на 0):

Результат:

I am going to divide 2 and 5
0.4
I am going to divide 2 and 0
Whoops! cannot divide

Під час виклику divide(2,5) викликається функція inner(), визначена в декораторі smart_divide(). Оскільки другий аргумент не є 0, то функція inner() повертає управління у вихідну функцію divide(), передаючи аргументи 2 та 5, і функція divide() проводить обчислення та повертає результат 0.4.

Аналогічно, під час виклику функції divide() з аргументами 2 та 0 функція inner() перевіряє, що значенням параметра b є 0, і виводить повідомлення про помилку, після чого повертає None.

Ланцюжок декораторів в Python

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

Результат:

***************
%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%
***************

Наступна частина коду:

рівнозначна

Порядок, у якому ми вибудовуємо ланцюжки декораторів, має значення. Якби ми змінили порядок на протилежний, наприклад:

То результат був би:

%%%%%%%%%%%%%%%
***************
Hello
***************
%%%%%%%%%%%%%%%

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (30 оцінок, середня: 5,00 з 5)
Завантаження...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *