Como frequentemente deve decoradores Python ser usado?
Pergunta
Recentemente, começou a experimentar com decoradores Python (e funções de ordem superior) porque parecia que eles poderiam fazer o meu unidade Django testa mais concisa. por exemplo, em vez de escrever:
def visit1():
login()
do_stuff()
logout()
Eu poderia, em vez fazer
@handle_login
def visit1():
do_stuff()
No entanto, após algumas experiências, descobri que decoradores não são tão simples como eu esperava. Primeiro, eu estava confuso com a sintaxe diferente decorador I encontrados em diferentes exemplos, até que eu aprendi que os decoradores se comportam de forma muito diferente quando eles levam argumentos . Então eu tentei decorar um método, e, eventualmente, aprendeu que não estava trabalhando porque eu primeiro tem que transformar o meu decorador em um descritor adicionando um método __get__
. Durante todo esse processo eu acabei confuso mais do que algumas vezes e ainda achar que a depuração este código "decorado" é mais complicado do que normalmente é para Python. Estou agora re-avaliar se eu realmente preciso decoradores no meu código, uma vez que a minha motivação inicial era para salvar um pouco de digitação, não porque não havia nada que realmente necessário funções de ordem superior.
Então, minha pergunta é: deve decoradores ser usado livremente ou com moderação? É cada vez mais Pythonic evitar usá-los?
Solução
Decoradores são muito bem em seu lugar e definitivamente não deve ser evitado - quando for o caso ;-). Vejo sua pergunta o que significa essencialmente "OK então quando são se apropriam"?
Adicionando um pouco de código de prefixo e / ou sufixo em torno de alguns, mas não todos os métodos de algumas classes é um exemplo bom. Se fosse todos os métodos, um class decorador para envolver todos os métodos seria melhor do que repetir @thisonetoo
infinitamente ;-). Se é uma vez em uma lua azul, então não vale a pena refatoração para wrappers (decoradores ou não). No meio, há um grande terreno onde decoradores são bastante adequados, de fato.
Tudo se resume a uma das regras de ouro da programação - SECO, para Do not Repeat Yourself. Quando você vê o seu código se tornar repetitivo, você pode refazer a repetição fora - e decoradores são uma excelente ferramenta para isso, embora eles estão longe de ser o único (métodos auxiliares e funções, metaclasses personalizados, geradores e outros iteradores, gerentes de contexto ... muitos dos recursos que adicionado ao Python ao longo dos últimos anos pode ser melhor pensado como dry-ajudantes, maneiras mais fácil e suave para fatorar esta ou aquela forma freqüente de repetição!).
Se não houver repetição, não há nenhuma chamada real para refatoração, portanto (em particular) nenhuma necessidade real para decoradores - em tais casos, YAGNI (Y'Ain't vai precisar dele) pode superar seca; -) <. / p>
Outras dicas
Alex já respondi a sua pergunta muito bem, o que eu gostaria de acrescentar é decoradores, faça o seu código muito mais fácil de entender. (Às vezes, mesmo se você está fazendo isso apenas uma vez).
Por exemplo, inicialmente, eu escrevo minhas opiniões Django, sem pensar sobre a autorização de todo. E quando, eu sou feito de escrevê-las, eu posso ver que precisa que os usuários autorizados e basta colocar um @login_required para eles.
Assim, qualquer pessoa que vem depois de mim pode em uma página ver o que opiniões são auth protegido.
E, claro, eles são muito mais DRY e colocar isso em todos os lugares.
Se não request.user.is_authenticated (): voltar HttpResponseREdiect (..)
Decoradores são uma forma de içar uma comum Aspect fora do seu código.
Programação proponentes irá dizer-lhe que há muitos aspectos comuns Orientada a Aspectos que AOP é essencial e central. Na verdade, você pode ler um debate tolo sobre este tema aqui:
Aspect Oriented Programming vs. Programação Orientada a Objetos
Existem alguns casos de uso comum para AOP. Você pode ler um pouco aqui:
Do que você usa AOP (Aspect Oriented Programming) na produção de software?
Há algumas preocupações transversais para que os decoradores são úteis.
-
controles de acesso ( "security") Autenticação, Autorização, Permissões, Proprietário
-
Logging (incluindo Depuração de ajudas e Auditoria)
-
Cache (muitas vezes uma implementação de Memoização )
-
Alguns tratamento de erros pode ser um aspecto comum e, portanto, adequados para a implementação decorador.
Há muito poucos outros padrões de design que são verdadeiramente transversal e merecem um decorador de AOP.
Se você tem o mesmo código no início e no fim de muitas funções, acho que justificaria a complexidade adicional de usar um decorador.
Um pouco como usar um bom (mas talvez complexo) modelo para um site com um monte de páginas, ele realmente economiza tempo e torna mais clara no final.