зачем использовать __xxx__ для определения свойства функции? - PullRequest
0 голосов
/ 25 мая 2018

Я новый питон здесь.У меня есть вопрос. Код такой:

def get(path):
    '''
    Define decorator @get('/path')
    '''
    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kw):
            return func(*args, **kw)
        wrapper.__method__ = 'GET'
        wrapper.__route__ = path
        return wrapper
    return decorator

Это декоратор, я не понимаю

"

  wrapper.__method__ = 'GET'
     wrapper.__route__ = path

" __xxx__"обычно используется для определения специальных методов и свойств, почему код определяет свойство функции, использующее стиль? Разве это не защищает? И может динамически добавлять атрибуты в функции, а также динамически добавлять атрибуты в класс? Огромное спасибо ~

1 Ответ

0 голосов
/ 25 мая 2018

Здесь действительно два вопроса: один о назначении произвольных атрибутов для функций, а другой о назначении специальных / двойных символов подчеркивания (подчеркивания) / магических атрибутов.

Назначение атрибутов функциям совершенно нормально.Согласно документам :

Функции являются объектами первого класса.

Это не означает автоматически, что вы можете назначать им атрибуты, ноэто хороший показатель.Объекты функций имеют доступную для записи __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"

...