Атрибут
A __name__
назначается для каждой функции python. Например,
>>> def f(*args, **kwargs):
... pass
...
>>> f.__name__
'f'
Теперь, если мы украшаем эту функцию каким-то декоратором, мы, по сути, возвращаем другую функцию с другим __name__
>>> def d(f):
... def w(*args, **kwargs):
... f(*args, **kwargs)
... return w
...
>>> f = d(f)
>>> f.__name__
'w'
Настоятельно рекомендуется использовать wraps
из functools
для декорирования возвращаемой функции, чтобы можно было скопировать такую информацию, как __name__
и __doc__
, в исходную функцию.
>>> from functools import wraps
>>> def d(f):
... @wraps(f)
... def w(*args, **kwargs):
... f(*args, **kwargs)
... return w
...
>>> f = d(f)
>>> f.__name__
'f'
Мой вопрос заключается в том, какие серьезные проблемы могут возникнуть если мы не используем wraps
для копирования информации? Что же такого важного в __name__
, что его нужно скопировать? Простой код, как и мой пример, работает нормально, если мы не используем wrap
.
Одна проблема, я могу подумать, если это сериализация. Например, Django не позволяет использовать лямбда-выражения (они безымянные) для использования в качестве значения по умолчанию для полей модели.
Может кто-нибудь добавить еще несколько проблемных c примеров? Тот же вопрос для декораторов классов.