Как часто следует использовать декораторы Python? - PullRequest
3 голосов
/ 28 июня 2009

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

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

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

@handle_login
def visit1():
    do_stuff()

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

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

Ответы [ 4 ]

12 голосов
/ 28 июня 2009

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

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

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

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

3 голосов
/ 28 июня 2009

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

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

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

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

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

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

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

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

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

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

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

3 голосов
/ 28 июня 2009

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

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

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

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

если нет request.user.is_authenticated (): return HttpResponseREdiect (..)

0 голосов
/ 28 июня 2009

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

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

...