Как часто следует использовать декораторы 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(..)
Декораторы - это способ вывести общий аспект из вашего кода.
Сторонники Аспектно-ориентированного Программирования скажут вам, что есть так много общих аспектов, что АОП является важным и центральным. Действительно, вы можете прочитать глупые дебаты на эту тему здесь:
Аспектно-ориентированное программирование против объектно-ориентированного программирования
Есть несколько общих случаев использования АОП. Вы можете прочитать несколько здесь:
Есть несколько сквозных проблем, для которых декораторы полезны.
Контроль доступа ("безопасность") Аутентификация, Авторизация, Разрешения, Владение
Ведение журнала (включая средства отладки и аудит)
Кэширование (часто реализация Memoization)
Некоторая обработка ошибок может быть общим аспектом и поэтому подходит для реализации декоратора.
Есть очень немного других шаблонов дизайна, которые действительно являются сквозными и заслуживают AOP-декоратора.
Если у вас есть один и тот же код в начале и конце многих функций, я думаю, это оправдало бы дополнительную сложность использования декоратора.
Скорее, как использование хорошего (но, возможно, сложного) шаблона для веб-сайта с большим количеством страниц, это действительно экономит время и добавляет ясности в конце.