Как создавать и использовать декораторы в Python
Узнайте, как писать и применять декораторы в Python. Освойте функции переноса, изменение поведения, обработку аргументов и сохранение метаданных с помощью переносов.
Обзор
Декораторы — одна из самых элегантных и мощных синтаксических функций Python, позволяющая изменять поведение функции или класса без постоянного изменения их кода. Они широко используются для решения сквозных задач, таких как регистрация времени выполнения, обеспечение аутентификации пользователей, кэширование результатов (мемоизация) и аудит конечных точек API.
По сути, декоратор — это функция высшего порядка, которая принимает другую функцию в качестве аргумента, определяет вложенную функцию-оболочку, которая внедряет некоторую пользовательскую логику, и возвращает эту функцию-оболочку. Python предоставляет понятный сокращенный синтаксис с использованием символа `@` для применения декораторов к функциям, что делает их визуально элегантными.
При написании декораторов обычно требуется, чтобы декорированная функция поддерживала любое количество позиционных и ключевых аргументов. Этого можно добиться, разработав вложенную функцию-оболочку, принимающую `*args` и `**kwargs` и передающую их целевой функции. Кроме того, вам следует использовать functools.wraps в функции-оболочке, чтобы сохранить строку документации и метаданные имени исходной функции.
Код и вывод выполнения
Этот скрипт демонстрирует написание декоратора журналирования и обертку функции для проверки входных, выходных данных и метаданных.
from functools import wraps
# 1. Defining a decorator
def log_execution(func):
@wraps(func) # Preserves original function metadata
def wrapper(*args, **kwargs):
print(f"[Log] Calling function: {func.__name__} with args: {args}")
result = func(*args, **kwargs)
print(f"[Log] Finished {func.__name__}. Result: {result}")
return result
return wrapper
# 2. Applying the decorator using @ syntax
@log_execution
def add_numbers(a, b):
"""Adds two numbers and returns the sum."""
return a + b
# 3. Invoking the decorated function
sum_result = add_numbers(15, 25)
print("Sum Result:", sum_result)
# Verifying metadata preservation
print("Docstring preserved:", add_numbers.__doc__)[Log] Calling function: add_numbers with args: (15, 25)
[Log] Finished add_numbers. Result: 40
Sum Result: 40
Docstring preserved: Adds two numbers and returns the sum.Пошаговая реализация
- Определите функцию внешнего декоратора, которая принимает целевую функцию в качестве аргумента.
- Импортируйте и примените @functools.wraps(func) к вложенной функции-оболочке, чтобы защитить исходные метаданные.
- Реализуйте оболочку(*args, **kwargs) для захвата входных переменных, внедрения логики и вызова целевой функции.
- Верните объект функции-обертки из блока заголовка декоратора.
- Примените декоратор, используя @decorator_name непосредственно над сигнатурой целевой функции.
Часто задаваемые вопросы
Почему @functools.wraps необходим внутри декораторов?
Без оберток декорированная функция теряет свою первоначальную идентичность (ее атрибуты __name__ и __doc__ заменяются атрибутами вложенной функции-обертки), что затрудняет отладку и самоанализ кода.
Могу ли я применить несколько декораторов к одной функции?
Да! Вы можете объединить декораторы, поместив в стек несколько строк @. Python применяет их снизу вверх (первой выполняется ближайшая к определению функции).
Связанные темы
Освойте *args и **kwargs в Python. Узнайте, как писать гибкие функции с динамическими позиционными и ключевыми аргументами, распаковывать коллекции и создавать функции-оболочки.
Как использовать лямбда-функции в PythonУзнайте, как использовать лямбда-функции в Python. Освойте анонимные функции, встроенные обратные вызовы и сортировку данных списка с помощью лямбда-ключей.
Рекомендуемые ресурсы Python
Расширьте свои знания с помощью соответствующих интерактивных руководств, шпаргалок и сравнений кода.
Объяснение переменных и типов данных Python
Понимать переменные Python и основные типы данных (строки, целые числа, числа с плавающей запятой, логические значения). Полное руководство для начинающих по распределению памяти в Python.
Шпаргалка по словарным методам Python
Изучите словарные методы Python. Полное справочное руководство по вставке, извлечению, обновлению и проверке пар ключ-значение.
Python против JavaScript: какой язык программирования лучше?
Всестороннее сравнение Python и JavaScript. Изучите синтаксические различия, производительность, варианты использования (серверная и клиентская части) и примеры кодирования.