Декораторы
Давайте предположим, что у нас есть несколько функций, которые что-то выводят, скажем, логи нашей программы.
from datetime import datetime def date_logger(): # Выводит текущую дату и время print(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) def connection_logger(connected): # Выводит статус соединения if connected: print("Connected") else: print("Not connected")
Мы где-то используем их в коде. Всё хорошо, но тут заказчик говорит, что перед каждым логом надо выводить "Log:". Зачем? А кто знает, надо и надо.
Конечно можно в начале каждой функции выводить это слово. Однако функций может быть много, а завтра заказчик захочет выводить другое слово. Хочется чего-то более универсального. Тут кто-то предложит глобальную переменную, но это не всегда лучший способ. Сегодня я вам расскажу про другой метод решения этой проблемы и имя ему декоратор.
Давайте рассмотрим следующую функцию - декоратор, которая "оборачивает" другую функцию:
def log_decorator(function): def wrapped(*args): # Вложенная функция-обёртка print("Log:", end=' ') function(*args) # Вызываем нашу функцию с параметрами return wrapped
А теперь давайте заменим наши функции на обёрнутые этой.
date_logger = log_decorator(date_logger) connection_logger = log_decorator(connection_logger)
Действительно, теперь, при вызове будет выводиться "Log: ". Казалось бы, проблема решена. Но как-то не эстетично это выглядит. Поэтому в питоне есть специальный синтаксис для декорации:
@<имя декоратора> def <декорируемая функция>(...): ...
То есть наши функции будут выглядеть следующим образом:
@log_decorator def date_logger(): # Выводит текущую дату и время print(datetime.now().strftime("%Y-%m-%d %H:%M:%S")) @log_decorator def connection_logger(connected): # Выводит статус соединения if connected: print("Connected") else: print("Not connected")
Отлично, но что, если я хочу сделать декоратор с параметром? Здесь надо создать функцию с параметром, которая будет возвращать декоратор. Например так:
def word_log_decorator(word): def decorator(function): def wrapped(*args): print(word, end=': ') function(*args) return wrapped return decorator
Вызывать эту функцию мы будем при декорации следующим образом:
@word_log_decorator("Log") def date_logger(): # Выводит текущую дату и время print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
При помощи декораторов ваш код может стать более понятным, однако стоит различать, когда имеет смысл поменять саму функцию, а когда написать декоратор.
Надеюсь, статья была вам полезной.
Надеюсь увидеть вас в моей группе SnakeBlog