Декоратор что такое: Декораторы в Python: понять и полюбить
Что такое декоратор? — Intermediate Python
Декораторы — важная часть Python. Если коротко: они являются функциями, которые изменяют работу других функций. Они помогают делать код короче и более «питонистичным». Большинство новичков не знает, где их использовать, так что я расскажу о нескольких случаях, когда декораторы помогут написать лаконичный код.
Для начала рассмотрим, как написать свой собственный декоратор.
Это будет самым сложным моментом в теме, поэтому мы будем продвигаться шаг за шагом, так что вы сможете все полностью понять.
Все в Python является объектом
Для начала краткая ретроспектива функций в Python:
def hi(name=»yasoob»):
return «Привет » + name
print(hi())
# Вывод: ‘Привет yasoob’
# Мы можем присвоить функцию переменной:
greet = hi
# Мы не используем здесь скобки, поскольку наша задача не вызвать функцию,
# а передать её объект переменной. Теперь попробуем запустить
print(greet())
# Вывод: ‘Привет yasoob’
# Посмотрим, что произойдет, если мы удалим ссылку на оригинальную функцию
del hi
print(hi())
# Вывод: NameError
print(greet())
# Вывод: ‘Привет yasoob’
Определение функций внутри функций
Итак, это были основы работы с функциями. Теперь продвинемся на шаг дальше. В Python разрешено объявлять функции внутри других функций:
def hi(name=»yasoob»):
print(«Вы внутри функции hi()»)
def greet():
return «Вы внутри функции greet()»
def welcome():
return «Вы внутри функции welcome()»
print(greet())
print(welcome())
print(«Вы внутри функции hi()»)
# Вывод: Вы внутри функции hi()
# Вы внутри функции greet()
# Вы внутри функции welcome()
# Вы внутри функции hi()
# Пример демонстрирует, что при вызове hi() вызываются также функции
# greet() и welcome(). Кроме того, две последние функции недоступны
# извне hi():
greet()
# Вывод: NameError: name ‘greet’ is not defined
Теперь мы знаем, что возможно определять функции внутри других функций. Другими словами: мы можем создавать вложенные функции. Теперь вам нужно познакомиться с еще одной возможностью функций: возвращать другие функции.
Возвращение функции из функции
Нам не обязательно исполнять функцию, определенную внутри другой функции сразу, мы можем вернуть её в качестве возвращаемого значения:
def hi(name=»yasoob»):
def greet():
return «Вы внутри функции greet()»
def welcome():
return «Вы внутри функции welcome()»
if name == «yasoob»:
return greet
return welcome
a = hi()
print(a)
# Вывод: <function greet at 0x7f2143c01500>
# Это наглядно демонстрирует, что переменная `a` теперь указывает на
# функцию greet() в функции hi(). Теперь попробуйте вот это
print(a())
# Вывод: Вы внутри функции greet()
Давайте еще раз пробежимся по коду. Через условный оператор мы возвращаем из функции объекты greet
и welcome
, а не greet()
и welcome()
. Почему? Потому что скобки означают вызов функции, без них мы просто передаем сам объект функции. Достаточно ясно? Давайте я чуть подробнее остановлюсь на этом. Когда мы пишем a = hi()
, функция hi()
исполняется и (поскольку имя по умолчанию yasoob) возвращается функция greet
. Если мы изменим код на
a = hi(name="ali")
, то будет возвращена функция welcome
. Мы также можем набрать hi()()
, что вернет Вы внутри функции greet()
.
Передаем функцию в качестве аргумента другой функции
def hi():
return «Привет yasoob!»
def doSomethingBeforeHi(func):
print(«Я делаю что-то скучное перед исполнением hi()»)
print(func())
doSomethingBeforeHi(hi)
# Вывод: Я делаю что-то скучное перед исполнением hi()
# Привет yasoob!
Теперь у нас есть все необходимые знания для изучения работы декораторов. Декораторы позволяют нам исполнять определенный код до и после исполнения конкретной функции.
Пишем наш первый декоратор
В прошлом примере мы по сути уже написали декоратор! Давайте изменим его и сделаем немного более полезным:
def a_new_decorator(a_func):
def wrapTheFunction():
print(«Я делаю что-то скучное перед исполнением a_func()»)
a_func()
print(«Я делаю что-то скучное после исполнения a_func()»)
return wrapTheFunction
def a_function_requiring_decoration():
print(«Я функция, которая требует декорации»)
a_function_requiring_decoration()
# Вывод: «Я функция, которая требует декорации»
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
# Теперь функция a_function_requiring_decoration обернута в wrapTheFunction()
a_function_requiring_decoration()
# Вывод: Я делаю что-то скучное перед исполнением a_func()
# Я функция, которая требует декорации
# Я делаю что-то скучное после исполнения a_func()
Все ясно? Мы просто использовали принципы, с которыми познакомились выше. Это то, чем и занимаются декораторы в Python! Они «обертывают» функцию и модифицируют её поведение определенным образом. Сейчас вы можете спросить, почему мы не используем в коде символ @. Это просто более короткий способ декорировать функции. Вот как мы можем модифицировать пример выше с использованием @:
@a_new_decorator
def a_function_requiring_decoration():
«»»Эй ты! Задекорируй меня полностью!»»»
print(«Я функция, которая требует декорации»)
a_function_requiring_decoration()
# Вывод: Я делаю что-то скучное перед исполнением a_func()
# Я функция, которая требует декорации
# Я делаю что-то скучное после исполнения a_func()
# Выражение @a_new_decorator это сокращенная версия следующего кода:
a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
Надеюсь, теперь у вас есть базовое представление о логике работы декораторов в Python. Однако, у нашего кода есть одна проблема. Если мы исполним:
print(a_function_requiring_decoration. __name__)
# Вывод: wrapTheFunction
Мы этого не ожидали! Имя функции должно быть a_function_requiring_decoration
. В реальности наша функция была заменена на wrapTheFunction. Она перезаписала имя и строку документации оригинальной функции. К счастью, Python предоставляет нам простой инструмент для обхода этой проблемы — functools.wraps
. Давайте исправим предыдущий пример, используя functools.wraps
:
from functools import wraps
def a_new_decorator(a_func):
@wraps(a_func)
def wrapTheFunction():
print(«Я делаю что-то скучное перед исполнением a_func()»)
a_func()
print(«Я делаю что-то скучное после исполнения a_func()»)
return wrapTheFunction
@a_new_decorator
def a_function_requiring_decoration():
«»»Эй ты! Задекорируй меня полностью!»»»
print(«Я функция, которая требует декорации»)
print(a_function_requiring_decoration. __name__)
# Вывод: a_function_requiring_decoration
Так намного лучше. Давайте двигаться дальше и знакомиться с конкретными вариантами использования декораторов.
Макет:
from functools import wraps
def decorator_name(f):
@wraps(f)
def decorated(*args, **kwargs):
if not can_run:
return «Функция не будет исполнена»
return f(*args, **kwargs)
return decorated
@decorator_name
def func():
return(«Функция исполняется»)
can_run = True
print(func())
# Вывод: Функция исполняется
can_run = False
print(func())
# Вывод: Функция не будет исполнена
Примечание: @wraps
принимает на вход функцию для декорирования и добавляет функциональность копирования имени, строки документации, списка аргументов и т. д. Это открывает доступ к свойствам декорируемой функции из декоратора.
Варианты использования
Теперь давайте рассмотрим области, где декораторы действительно показывают себя и существенно упрощают работу.
Авторизация
Декораторы могут использоваться в веб-приложениях для проверки авторизации пользователя перед тем, как открывать ему доступ к функционалу. Они активно используются в веб-фреймворках Flask и Django. Вот пример проверки авторизации на декораторах:
Пример:
from functools import wraps
def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
authenticate()
return f(*args, **kwargs)
return decorated
Журналирование
Журналирование — другая область, в которой декораторы находя широкое применение. Вот пример:
from functools import wraps
def logit(func):
@wraps(func)
def with_logging(*args, **kwargs):
print(func.__name__ + » была исполнена»)
return func(*args, **kwargs)
return with_logging
@logit
def addition_func(x):
«»»Считаем что-нибудь»»»
return x + x
result = addition_func(4)
# Вывод: addition_func была исполнена
Уверен, вы уже думаете о каком-нибудь хитром использовании декораторов.
Декораторы с аргументами
Тогда подумайте вот о чем, является ли @wraps
также декоратором? Но, @wraps
же принимает аргумент, как нормальная функция. Тогда почему бы нам не сделать что-то похожее с нашими декораторами?
Когда мы используем синтаксис @my_decorator
мы применяем декорирующую функцию с декорируемой функцией в качестве параметра. Как вы помните, все в Python является объектом, в том числе и функции! Помня это, мы можем писать функции, возвращающие декорирующие функции.
Вложенные декораторы внутри функции
Давайте вернемся к нашему примеру с журналированием и напишем декоратор, который позволит нам задавать файл для сохранения логов:
from functools import wraps
def logit(logfile=’out.log’):
def logging_decorator(func):
@wraps(func)
def wrapped_function(*args, **kwargs):
log_string = func.__name__ + » была исполнена»
print(log_string)
# Открываем логфайл и записваем данные
with open(logfile, ‘a’) as opened_file:
# Мы записываем логи в конкретный файл
opened_file.write(log_string + ‘\n’)
return wrapped_function
return logging_decorator
@logit()
def myfunc1():
myfunc1()
# Вывод: myfunc1 была исполнена
# Файл out.log создан и содержит строку выше
@logit(logfile=’func2. log’)
def myfunc2():
myfunc2()
# Вывод: myfunc2 была исполнена
# Файл func2.log создан и содержит строку выше
Декораторы из классов
Теперь наш журналирующий декоратор находится на продакшене, однако, когда отдельные части приложения являются критичными, мы определенно хотим отзываться на возникающие ошибки как можно быстрее. Давайте предположим, что иногда мы просто хотим записывать логи в файл, а иногда мы хотим получать сообщения об ошибках по email, сохраняя логи в тоже время. Это подходящий случай для использования наследования, однако, до сих пор мы встречали только декораторы-функции.
К счастью, классы также можно использовать для создания декораторов. Давайте опробуем эту методику:
class logit(object):
def __init__(self, logfile=’out.log’):
self.logfile = logfile
def __call__(self, func):
log_string = func.__name__ + » была исполнена»
print(log_string)
# Открываем логфайл и записваем данные
with open(self. logfile, ‘a’) as opened_file:
# Мы записываем логи в конкретный файл
opened_file.write(log_string + ‘\n’)
# Отправляем сообщение
self.notify()
def notify(self):
# Только записываем логи
Такое решение имеет дополнительно преимущество в краткости, в сравнении с вложенными функциями, при этом синтаксис декорирования функции остается прежним:
@logit()
def myfunc1():
Теперь давайте возьмем подкласс logit
и добавим функционал отправки email (эта тема не будет здесь рассмотрена):
class email_logit(logit):
Реализация logit для отправки писем администраторам при вызове
функции
def __init__(self, email='[email protected]’, *args, **kwargs):
self.email = email
super(email_logit, self).__init__(*args, **kwargs)
def notify(self):
# Отправляем письмо в self.email
# Реализация не будет здесь приведена
@email_logit
будет работать также как и @logit
, при этом отправляя сообщения на почту администратору помимо журналирования.
Декораторы в Python / Skillbox Media
#статьи
- 11
На собеседованиях только и разговоров, что о декораторах. Разбираемся на пальцах, что это.
Vkontakte Twitter Telegram Скопировать ссылкуЦокто Жигмытов
Кандидат философских наук, специалист по математическому моделированию. Пишет про Data Science, AI и программирование на Python.
Итак, вы на собеседовании на вакансию джуна-пайтониста. Всё идёт хорошо: вы объяснили про кортежи и списки, про принципы ООП и структуры данных, даже решили небольшую задачку, и вдруг:
— Расскажите, пожалуйста, про декораторы в Python.
В большинстве случаев будет достаточно сказать своими словами, что такое декоратор, и написать простейший код.
Вслух:
— Декоратор, если в двух словах, это функция, которая добавляет новую функциональность к другой функции без изменения её кода. Он как бы оборачивает, декорирует функцию, тем самым расширяя её возможности.
Пример кода:
Функция say_hi (пример отсюда), которую мы «обернём» в декоратор, возвращает строку «всем привет». Обратите внимание: не печатает, а возвращает.
def say_hi():
return 'всем привет'
А наш декоратор превратит символы этой строки из строчных в прописные. Этой возможности у функции say_hi
Пишем декоратор:
def uppercase_decorator(function):
def wrapper():
func = function()
make_uppercase = func.upper()
return make_uppercase
return wrapper
Что здесь происходит — разбираем код построчно:
- В первой строке мы указываем имя декоратора и то, что он принимает function в качестве своей переменной.
- Вторая строка — это объявление функции-обёртки wrapper (). Тело обёртки в блоке состоит из трёх строк ниже. Оно как раз и описывает, что именно мы будем делать с функцией, ранее принятой декоратором.
- Третья строка: записываем входящую переменную function () в локальную переменную func. Здесь «локальная» означает, что она действует только в рамках функции wrapper ().
- Четвёртая строка: мы применяем к func строковый метод upper и записываем результат в другую локальную переменную make_uppercase.
Больше локальных переменных богу локальных переменных! Конечно, всё это ради понятности и читаемости.
- Пятая строка: функция wrapper () возвращает переменную make_uppercase, то есть строку от function (), но уже прописными буквами.
- Последняя строка: декоратор возвращает нам уже саму функцию wrapper, точнее, результат её работы над функцией function.
Как это запустить? Пишем символ @, за ним название декоратора, а объявление функции say_hi переносим на строку под ней:
@uppercase_decorator
def say_hi():
return 'всем привет'
Печатаем вывод декорированной функции:
print(say_hi())
Получаем на выходе:
ВСЕМ ПРИВЕТ
Если хочется немного дополнить, вот ещё примеры декораторов.
def logging(func):
def log_function_called():
print(f'Вызвана {func}')
func()
return log_function_called
@logging
def my_name():
print('Крис')
@logging
def friends_name():
print('Наруто')
my_name()
friends_name()
ИсточникЧто здесь происходит:
Декоратор принимает в качестве переменной функцию func
. Затем функция-обёртка log_function_called печатает «Вызвана func» и запускает её на выполнение.
def benchmark(func):
import time
def wrapper():
start = time.time()
func()
end = time.time()
print('[*] Время выполнения: {} секунд.'.format(end - start))
return wrapper
@benchmark
def fetch_webpage():
import requests
webpage = requests.get('https://skillbox.ru')
print(webpage)
fetch_webpage()
ИсточникЧто здесь происходит:
В объявлении декоратора benchmark мы импортируем библиотеку time. В функции-обёртке wrapper засекаем время в переменную start, затем выполняем полученную декоратором функцию, а после этого фиксируем время в переменную
Сама функция fetch_webpage делает простой GET-запрос на наш сайт. Для этого она импортирует популярную библиотеку requests, записывает в переменную webpage ответ сервера Skillbox на запрос и печатает эту переменную.
В обёрнутом виде декоратор «запускает секундомер», функция fetch_webpage делает запрос и печатает ответ, после чего декоратор «выключает секундомер» и печатает время, которое функция потратила на всю эту работу.
Если хотите произвести впечатление, то можно добавить, что:
- Декоратор — это паттерн проектирования (design pattern) в Python, а также функция второго уровня, то есть принимающая другие функции в качестве переменных и возвращающая их.
- И в сам декоратор, и в функцию-обёртку можно передать и позиционные, и именованные аргументы — args и kwargs соответственно.
- Декораторы работают не только с функциями, но и с классами и методами.
Конечно, на собеседовании надо будет пояснить все эти пункты и проиллюстрировать их кодом. На курсе Профессия Python-разработчик вы изучите не только декораторы, но и всё необходимое для того, чтобы с блеском проходить любые собеседования.
Читайте также:
Учись бесплатно:
вебинары по программированию, маркетингу и дизайну.
Против Microsoft подали иск на 9 млрд долларов за воровство кода для сервиса Copilot 11 ноя 2022
Хакеры заражали компьютеры с помощью клона графического редактора GIMP 10 ноя 2022
Дочерняя компания Cisco заблокировала российских пользователей и просит вернуть железо 08 ноя 2022
Понравилась статья?
Да
Decorators in Python — GeeksforGeeks
Decorators — очень мощный и полезный инструмент в Python, поскольку он позволяет программистам изменять поведение функции или класса. Декораторы позволяют нам обернуть другую функцию, чтобы расширить поведение обернутой функции, не изменяя ее навсегда. Но прежде чем углубиться в декораторы, давайте разберемся с некоторыми понятиями, которые пригодятся при изучении декораторов.
Объекты первого класса
В Python функции объекты первого класса , что означает, что функции в Python могут использоваться или передаваться в качестве аргументов.
Свойства функций первого класса:
- Функция является экземпляром типа Объект.
- Вы можете сохранить функцию в переменной.
- Вы можете передать функцию в качестве параметра другой функции.
- Вы можете вернуть функцию из функции.
- Вы можете хранить их в структурах данных, таких как хэш-таблицы, списки и т. д.
Рассмотрим приведенные ниже примеры для лучшего понимания.
Пример 1: Обработка функций как объектов.
Python3
|
:
Hello. HELLO
В приведенном выше примере мы присвоили функцию Shout переменной. Это не вызовет функцию, вместо этого он берет объект функции, на который ссылается крик, и создает второе имя, указывающее на него, крик.
Пример 2: Передача функции в качестве аргумента
Python3
|
Output:
HI , Я СОЗДАН ФУНКЦИЕЙ, ПЕРЕДАВАЕМОЙ В КАЧЕСТВЕ АРГУМЕНТА.привет, меня создала функция, переданная в качестве аргумента.
В приведенном выше примере функция приветствия принимает в качестве параметра другую функцию (в данном случае крик и шепот). Затем функция, переданная в качестве аргумента, вызывается внутри функции приветствия.
Пример 3: Возврат функций из другой функции.
Python3
|
Output:
25
In the выше, мы создали функцию внутри другой функции, а затем вернули функцию, созданную внутри.
В приведенных выше трех примерах показаны важные понятия, необходимые для понимания декораторов. Пройдя через них, давайте теперь углубимся в декораторы.
Декораторы
Как указано выше, декораторы используются для изменения поведения функции или класса. В декораторах функции передаются в качестве аргумента другой функции, а затем вызываются внутри функции-оболочки.
Синтаксис декоратора:
@gfg_decorator определение hello_decorator(): печать("Гфг") '''Приведенный выше код эквивалентен - определение hello_decorator(): печать("Гфг") hello_decorator = gfg_decorator(hello_decorator)'''
В приведенном выше коде gfg_decorator является вызываемой функцией, которая добавит некоторый код поверх какой-либо другой вызываемой функции, функции hello_decorator, и вернет функцию-оболочку.
Decorator can modify the behaviour :
Python3
0002
|
функция до выполнения4, Вывод: Давайте посмотрим на поведение приведенного выше кода и на то, как он работает шаг за шагом при вызове «function_to_be_used». Давайте перейдем к другому примеру, где мы можем легко узнать время выполнения функции с помощью декоратора. Вывод: Во всех приведенных выше примерах функции ничего не возвращали, поэтому проблемы не было, но возвращаемое значение может понадобиться. Вывод: В приведенном выше примере вы можете заметить большую разницу в параметрах внутренней функции. Внутренняя функция принимает аргумент как *args и **kwargs, что означает, что кортеж позиционных аргументов или словарь аргументов ключевого слова может быть передан любой длины. Это делает его общим декоратором, который может украшать функцию с любым количеством аргументов. Проще говоря, цепочка декораторов означает украшение функции несколькими декораторами. Example: Вывод: Вышеприведенный пример подобен вызову функции как – Декоратор принимает функцию, добавляет некоторую функциональность и возвращает ее. В этом уроке вы узнаете, как создать декоратор и почему вам следует его использовать. В Python есть интересная функция под названием декораторы для добавления функциональности в существующий код. Это также называется метапрограммированием , потому что часть программы пытается модифицировать другую часть программы во время компиляции. Чтобы понять декораторы, мы должны сначала узнать несколько основных вещей в Python. Нам должно быть комфортно с тем фактом, что все в Python (Да! Даже классы) является объектами. Имена, которые мы определяем, являются просто идентификаторами, привязанными к этим объектам. Функции не являются исключением, они тоже объекты (с атрибутами). Различные имена могут быть связаны с одним и тем же функциональным объектом. Вот пример. Выход Когда вы запускаете код, обе функции Теперь все становится еще более странным. Функции могут быть переданы в качестве аргументов другой функции. Если вы использовали такие функции, как Такие функции, которые принимают другие функции в качестве аргументов, также называются функциями высшего порядка . Вот пример такой функции. Мы вызываем функцию следующим образом. Кроме того, функция может возвращать другую функцию. Вывод Здесь Наконец, мы должны знать о замыканиях в Python. Функции и методы вызываются callable как их можно вызвать. Фактически, любой объект, реализующий специальный метод По сути, декоратор принимает функцию, добавляет некоторые функции и возвращает ее. Когда вы запускаете следующие коды в оболочке, В показанном выше примере Функция Мы видим, что функция декоратора добавила некоторые новые функции к исходной функции. Это похоже на упаковку подарка. Декоратор действует как обертка. Характер украшенного предмета (настоящего подарка внутри) не меняется. Но теперь он выглядит красиво (так как он был украшен). Как правило, мы украшаем функцию и переназначаем ее как Это обычная конструкция, и по этой причине в Python есть синтаксис, упрощающий ее. Мы можем использовать символ эквивалентен Это просто синтаксический сахар для реализации декораторов. Приведенный выше декоратор был простым и работал только с функциями, у которых не было параметров. Эта функция имеет два параметра: a и b . Мы знаем, что это выдаст ошибку, если мы передадим b как 0. Теперь давайте сделаем декоратор для проверки этого случая, который вызовет ошибку. Эта новая реализация вернет Таким образом мы можем декорировать функции, которые принимают параметры. Внимательный наблюдатель заметит, что параметры вложенной функции В Python эта магия выполняется как Несколько декораторов могут быть объединены в цепочку в Python. То есть функцию можно декорировать несколько раз разными (или одними и теми же) декораторами. Мы просто размещаем декораторы над нужной функцией. Это внутри функции !!
Это после выполнения функции
Python3
Импорт
Время
Импорт
MATH
DEF
9
DEF
9
DEF
9.0040
def
inner1(
*
args,
*
*
kwargs):
Начало
=
Время ()
func(
*
args,
*
*
kwargs)
end
=
time.
time()
Печать
(
"Всего времени, взятого в:"
, func .__ name__, End
-
начало)
Возврат
0039 inner1
@calculate_time
def
factorial(num):
time.
sleep(
2
)
Печать
(Математика. Факториал (NUM))
Фактор (
10
)
90 900 9003 3628800
Общее время, затраченное на: factorial 2.0061802864074707
Что, если функция что-то возвращает или функции передается аргумент?
Python3
def
hello_decorator(func):
def
inner1(
*
args,
*
*
kwargs):
print
(
"before Execution"
)
возвращался_value
=
Func (
*
Args,
*
*
kwargs)
print
(
"after Execution"
)
return
returned_value
возврат
внутренний1
@hello_decorator
def
sum_two_numbers(a, b):
print
(
"Inside the function"
)
return
a
+
b
A, B
=
1
,
2
Печать
(
".
0040
перед выполнением
Внутри функции
после казни
Sum = 3
Цепочка декораторов
Python3
def
decor1(func):
def
inner():
x
=
func ()
возврат
x
*
x
return
inner
def
decor(func):
def
inner():
x
=
Func ()
Возврат
2
*
x
возврат
.
0040
@decor1
@decor
def
num():
return
10
print
(num())
400
decor1(decor(num))
Как это сделать?
Декораторы в Python
Необходимые условия для обучения декораторов
по умолчанию сначала (сообщение):
печать (сообщение)
первый("Привет")
второй = первый
второй ("Привет")
Привет
Hello
first
и second
дают одинаковый результат. Здесь имена first
и second
относятся к одному и тому же функциональному объекту. карта
, фильтр
и уменьшить
в Python, то вы об этом уже знаете. по умолч. вкл.(х):
вернуть х + 1
деф дек(х):
возврат х - 1
def работать (функция, х):
результат = функция (х)
возвращаемый результат
>>> работать(вкл.3)
4
>>> работать(дек,3)
2
по определению is_call():
защита is_returned():
распечатать("Привет")
возврат is_returned
новый = is_вызванный ()
# Выводит "Привет"
новый()
Привет
is_returned()
— это вложенная функция, которая определяется и возвращается каждый раз, когда мы вызываем is_call()
. Возвращаясь к декораторам
__call__()
, называется вызываемым. Таким образом, в самом общем смысле декоратор — это вызываемый объект, который возвращает вызываемый объект. по определению make_pretty(func):
защита внутренняя():
print("Меня наградили")
функция()
вернуться внутрь
обычный ():
print("Я обычный")
>>> обычный()
я обычный
>>> # украсим эту обычную функцию
>>> довольно = make_pretty(обычный)
>>> красивая ()
меня украсили
Я обычный
make_pretty()
является декоратором. На шаге присваивания: pretty = make_pretty(ordinary)
normal()
была украшена, а возвращаемой функции было присвоено имя красивая
. обычный = make_pretty(обычный).
@
вместе с именем функции-декоратора и поместить его над определением декорируемой функции. Например, @make_pretty
обычный ():
print("Я обычный")
def обычный():
print("Я обычный")
обычный = make_pretty(ordinary)
Декорирование функций параметрами
Что, если бы у нас были функции, принимающие такие параметры, как:
по умолч. разделить(а, б):
return a/b
>>> делить(2,5)
0,4
>>> разделить(2,0)
Traceback (последний последний вызов):
...
ZeroDivisionError: деление на ноль
по определению smart_divide(func):
определение внутреннее (а, б):
print("Я буду делить", а, "и", б)
если б == 0:
print("Упс! Делить нельзя")
возвращаться
функция возврата (а, б)
вернуться внутрь
@smart_divide
Деф разделить (а, б):
печать (а/б)
Нет
, если возникнет ошибка. >>> разделить(2,5)
Я собираюсь разделить 2 и 5
0,4
>>> разделить(2,0)
Я собираюсь разделить 2 и 0
Упс! нельзя делить
inner()
внутри декоратора совпадают с параметрами функций, которые он украшает. Принимая это во внимание, теперь мы можем делать общие декораторы, работающие с любым количеством параметров. function(*args, **kwargs)
. Таким образом, аргументов
будет кортежем позиционных аргументов, а kwargs
будет словарем аргументов ключевого слова. Примером такого декоратора будет: defworks_for_all(func):
def внутренний (*args, **kwargs):
print("Я могу украсить любую функцию")
функция возврата (*args, **kwargs)
return inner
Объединение декораторов в цепочку в Python