Здесь действительно два вопроса: один о назначении произвольных атрибутов для функций, а другой о назначении специальных / двойных символов подчеркивания (подчеркивания) / магических атрибутов.
Назначение атрибутов функциям совершенно нормально.Согласно документам :
Функции являются объектами первого класса.
Это не означает автоматически, что вы можете назначать им атрибуты, ноэто хороший показатель.Объекты функций имеют доступную для записи __dict__
1 , что делает возможной настройку атрибутов.Это преднамеренная и часто используемая функция.Следующий вопрос SO раскрывает тему: Атрибуты функции Python - использует и злоупотребляет .
Проблема с показанным кодом связана с неправильным использованием атрибутов dunder.По сути, использование атрибутов dunder для чего-либо кроме официально документированного использования - это плохая идея :
Любое использование __*__
имен в любом контексте,который не следует явно задокументированному использованию, может быть поврежден без предупреждения.
Здесь есть две специфические проблемы.Основная проблема заключается в том, что добавление недокументированных атрибутов dunder может потенциально конфликтовать с обычными атрибутами вызываемых атрибутов, установленными functools.wraps
(перечисленными в Модель данных 1 ).Вторичная проблема заключается в том, что добавление атрибутов dunder может добавить нежелательное поведение к объекту при определенных обстоятельствах, поскольку интерпретатор использует их как флаги.
Существует ряд альтернативных соглашений об именах, о которых следует помнить,который был бы более уместным, чем метод dunder:
- Например, переименование
__method__
в _method
сделало бы его "закрытым по соглашению", так как Python на самом деле не распознает концепцию конфиденциальность как таковая. - Модифицированная версия
_method
будет _method_
.Это соглашение, которое используется встроенным пакетом enum
именно для того, чтобы избежать путаницы зарезервированных имен. - Использование простого имени, конечно, всегда хорошо:
method
вместо __method__
. - Схема именования, которая будет не работать, будет
__method
.Это вызывает искажение имени переводчиком, поэтому имя будет недоступно для вызывающего.Это было бы гораздо худшей идеей, чем просто использование более точных имен, что не вызовет особых проблем для любого переводчика, которого я знаю в данный момент.
TL; DR
Назначение атрибутов функции довольно полезно и полностью поддерживается.Присвоение атрибутов dunder, однако, в лучшем случае сомнительно.
1 Прокрутите вниз до "Callable Types"