description
, author
или version
. Для сохранения исходной сигнатуры декорируемой функции важно использовать functools.wraps
. Пример:
import functools
def add_metadata(description, author):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
wrapper.description = description
wrapper.author = author
return wrapper
return decorator
@add_metadata(description="Функция для сложения двух чисел.", author="John Doe")
def add(x, y):
return x + y
print(add.description)
print(add.author)
Декораторы в Python позволяют элегантно добавлять метаданные к функциям, не изменяя их основной код. Метаданные могут быть полезны для документирования, introsкции, инструментов анализа кода, и для различных других целей.
Основная идея: Декоратор - это функция, которая принимает другую функцию в качестве аргумента, расширяет её функциональность и возвращает расширенную функцию. Мы можем использовать это, чтобы добавлять атрибуты к декорируемой функции.
Пример:
import functools
def add_metadata(metadata):
def decorator(func):
@functools.wraps(func) # Важно для сохранения исходной информации о функции
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
for key, value in metadata.items():
setattr(wrapper, key, value) # Добавляем метаданные как атрибуты
return wrapper
return decorator
@add_metadata({'description': 'Эта функция выполняет сложение.', 'author': 'AI Assistant'})
def add(x, y):
"""Складывает два числа."""
return x + y
print(add.description) # Выведет: Эта функция выполняет сложение.
print(add.author) # Выведет: AI Assistant
print(add.__doc__) # Выведет: Складывает два числа.
print(add.__name__) # Выведет: add (благодаря functools.wraps)
Разъяснения:
add_metadata(metadata)
: Это наш декоратор, который принимает словарь metadata
с парами ключ-значение, которые мы хотим добавить к функции.decorator(func)
: Эта вложенная функция принимает декорируемую функцию func
.@functools.wraps(func)
: Ключевой момент! Эта строка импортирует и использует functools.wraps
, который гарантирует, что обертка wrapper
сохраняет важную информацию об исходной функции func
, такую как её __name__
(имя), __doc__
(строка документации), и т.д. Без этого декоратора, add.__name__
выведет "wrapper" вместо "add", что затруднит отладку и понимание кода.wrapper(*args, **kwargs)
: Это функция-обертка, которая вызывает исходную функцию func
с переданными аргументами. Мы добавляем атрибуты *перед* возвратом этой обертки. Если нужно как-то изменять поведение функции, это место, где это нужно делать. В данном примере, мы просто вызываем исходную функцию без изменений.setattr(wrapper, key, value)
: Мы перебираем пары ключ-значение в словаре metadata
и используем setattr
для добавления этих значений как атрибутов к обертке wrapper
.return wrapper
: Декоратор возвращает модифицированную функцию (в данном случае, обертку с добавленными атрибутами).@add_metadata(...)
: Синтаксис декоратора, который применяет декоратор add_metadata
к функции add
.Почему это важно?
Альтернативные подходы (менее предпочтительные):
func.__dict__.update(metadata)
также работает, но setattr
является более стандартным и читаемым способом.В заключение, использование декораторов с setattr
и functools.wraps
- это мощный и рекомендуемый способ добавления метаданных к функциям в Python, обеспечивающий чистый, поддерживаемый и гибкий код.