Как часто следует использовать декораторы Python?

Недавно я начал экспериментировать с Python-декораторами (и функциями более высокого порядка), потому что казалось, что они могут сделать мои модульные тесты Django более лаконичными. например, вместо того, чтобы писать:

def visit1():
    login()
    do_stuff()
    logout()

Я мог бы вместо этого сделать

@handle_login
def visit1():
    do_stuff()

Однако после некоторых экспериментов я обнаружил, что декораторы не так просты, как я надеялся. Во-первых, меня смутил другой синтаксис декоратора, который я обнаружил в разных примерах, пока не узнал, что декораторы ведут себя очень по-разному, когда принимают аргументы. Затем я попытался украсить метод и в итоге узнал, что он не работает, потому что сначала мне нужно превратить свой декоратор в дескриптор, добавив __get__ метод. В течение всего этого процесса я несколько раз путался, и все же обнаружил, что отладка этого "украшенного" кода сложнее, чем обычно для Python. Сейчас я переоцениваю, действительно ли мне нужны декораторы в моем коде, так как моей первоначальной мотивацией было сэкономить немного ввода, а не потому, что было что-то, что действительно требовало функций высшего порядка.

Итак, мой вопрос: должны ли декораторы использоваться свободно или экономно? Является ли когда-либо более Pythonic, чтобы избежать их использования?

4 ответа

Решение

Декораторы хороши на своем месте и определенно их не следует избегать - когда это уместно;-). Я вижу, что ваш вопрос по сути означает "ОК, тогда когда они уместны"?

Хорошим примером является добавление некоторого префиксного и / или постфиксного кода для некоторых, но не для всех методов некоторых классов. Если бы все это было методами, декоратор класса для переноса всех методов был бы лучше, чем повторение @thisonetoo бесконечно;-). Если это когда-то в голубой луне, то не стоит рефакторинга для оберток (декораторов или иным образом). В середине есть большая площадка, где декораторы действительно подходят.

Это сводится к одному из золотых правил программирования - СУХОЙ, для Не повторяйся. Когда вы видите, что ваш код становится повторяющимся, вы должны реорганизовать повторение - и декораторы являются отличным инструментом для этого, хотя они далеко не единственные (вспомогательные методы и функции, пользовательские метаклассы, генераторы и другие итераторы, менеджеры контекста).... многие из функций, которые мы добавили в Python за последние несколько лет, лучше всего рассматривать как DRY-помощники, более простые и плавные способы выделить ту или иную частую форму повторения!).

Если нет повторения, то нет никакого реального требования к рефакторингу, следовательно (в частности) нет реальной необходимости в декораторах - в таких случаях YAGNI (Y'An't Gonna Need It) может превзойти DRY;-).

Алекс уже хорошо ответил на ваш вопрос, я бы добавил, что это декораторы, которые сделают ваш код НАМНОГО проще для понимания. (Иногда, даже если вы делаете это только один раз).

Например, изначально я пишу свои взгляды на Django, даже не думая об авторизации. И когда я закончу их писать, я смогу увидеть, кому нужны авторизованные пользователи, и просто добавлю для них @login_required.

Таким образом, любой, кто придет за мной, сможет одним взглядом увидеть, какие виды защищены аутентификацией.

И, конечно, они намного более СУХИЕ и помещают это всюду.

если нет request.user.is_authenticated(): вернуть HttpResponseREdiect(..)

Декораторы - это способ вывести общий аспект из вашего кода.

Сторонники Аспектно-ориентированного Программирования скажут вам, что есть так много общих аспектов, что АОП является важным и центральным. Действительно, вы можете прочитать глупые дебаты на эту тему здесь:

Аспектно-ориентированное программирование против объектно-ориентированного программирования

Есть несколько общих случаев использования АОП. Вы можете прочитать несколько здесь:

Используете ли вы AOP (Аспектно-ориентированное программирование) в производственном программном обеспечении?

Есть несколько сквозных проблем, для которых декораторы полезны.

  • Контроль доступа ("безопасность") Аутентификация, Авторизация, Разрешения, Владение

  • Ведение журнала (включая средства отладки и аудит)

  • Кэширование (часто реализация Memoization)

  • Некоторая обработка ошибок может быть общим аспектом и поэтому подходит для реализации декоратора.

Есть очень немного других шаблонов дизайна, которые действительно являются сквозными и заслуживают AOP-декоратора.

Если у вас есть один и тот же код в начале и конце многих функций, я думаю, это оправдало бы дополнительную сложность использования декоратора.

Скорее, как использование хорошего (но, возможно, сложного) шаблона для веб-сайта с большим количеством страниц, это действительно экономит время и добавляет ясности в конце.

Другие вопросы по тегам