Шаг 49.
Python: тонкости программирования. Эффективные функции. Сила декораторов. Как писать "отлаживаемые" декораторы

    На этом шаге мы дадим несколько советов по написанию декораторов.

    При использовании декоратора вы на самом деле только подменяете одну функцию другой. Оборотной стороной этого процесса является то, что он "скрывает" некоторые метаданные, закрепленные за оригинальной (недекорированной) функцией.

    Например, оригинальное имя функции, ее строка документации docstring и список параметров скрыты замыканием-оберткой:

>>> def greet():
	"""Вернуть дружеское приветствие."""
	return 'Привет!'

>>> decorated_greet = uppercase(greet)

    При попытке получить доступ к каким-либо из этих метаданных функции вместо них вы увидите метаданные замыкания-обертки:

>>> greet.__name__	
'greet'
>>> greet.__doc__	
'Вернуть дружеское приветствие.'
>>> decorated_greet.__name__
'wrapper'
>>> decorated_greet.__doc__
None

    Это делает отладку и работу с интерпретатором Python неуклюжей и трудоемкой. К счастью, существует быстрое решение этой проблемы: декоратор functools.wraps, включенный в стандартную библиотеку Python.


См. документацию Python "functools": https://docs.python.org/3/library/functools.html.

    Декоратор functools.wraps можно использовать в своих собственных декораторах для того, чтобы копировать потерянные метаданные из недекорированной функции в замыкание декоратора. Вот пример:

>>> import functools
>>> def uppercase(func):
	@functools.wraps(func)
	def wrapper():
		return func().upper()
	return wrapper

    Применение декоратора functools.wraps к замыканию-обертке, возвращаемому декоратором, переносит в него строку документации и другие метаданные входной функции:

>>> @uppercase
def greet():
	"""Вернуть дружеское приветствие."""
	return 'Привет!'

>>> greet.__name__
'greet'
>>> greet.__doc__
'Вернуть дружеское приветствие.'

    В качестве оптимального практического приема рекомендуем использовать декоратор functools.wraps во всех декораторах, которые вы пишете сами. Это не займет много времени и поможет в будущем при отладке.

    Мы успешно добрались до самого конца этого сложного раздела и многое узнали о декораторах в Python. Отличная работа!

    На следующем шаге мы подведем итог по изученному материалу.




Предыдущий шаг Содержание Следующий шаг