Python Decorators – Como Decorar o Seu Código com Classe

Python Decorators, ou apenas “decoradores” é um recurso muito poderoso da linguagem Python!

Trabalhar com decorators em Python é uma maneira simples e elegante de alterar e/ou complementar o comportamento de um determinado bloco de código sem alterá-lo diretamente.

python

Introdução aos Python Decorators

Neste artigo nós iremos aprender como trabalhar com decorators na linguagem Python.

Mas afinal, o que são decorators?




O que são Decorators em Python?

Um decorator é, por definição, uma função que recebe outra função, complementando o comportamento da função passada, porém sem alterá-la diretamente.

Ou seja, os Python Decorators oferecem uma maneira simples e elegante de chamarmos funções de ordem  superior.

Como decorators são muito utilizados através de funções, vamos dar uma olhada mais a fundo nas funções em python!

Funções em Python

Como já foi dito no artigo que eu escrevi sobre funções em Python, elas não são nada mais do blocos de código reutilizáveis.

O que nós precisamos focar aqui, é o fato de funções serem First Class Citizen em Python, ou seja, são objetos/entidades de primeira classe.




Mas o que isso quer dizer afinal?

Tratar funções como um cidadão de primeira classe é permitir que que elas sejam tratadas e tenham o direito a operações que outros objetos também tenham, como por exemplo, serem passadas como argumentos em outras funções, serem retornadas por funções, etc.

Aqui vale a pena relembrar que afinal, tudo no Python é um objeto, lembra?! Logo, funções também são tratadas como os outros objetos.

Vamos ver um pouco de código para ilustrar as coisas:


Como podemos ver acima, nós podemos definir uma variável como sendo uma função, podemos passar funções por parâmetros, e por ai vai.




Nested Functions em Python

E já que funções são first class citizen, e nós podemos por exemplo, criar uma variável dentro de uma função, nós podemos também definir uma outra função dentro de funções.


Legal, você não acha?

xkcd: python

Retornando Funções em Python

E como nós já falamos, é possível também criar funções que retornarão funções:


Mas se estamos escrevendo sobre Python Decorators, porque a gente está vendo sobre funções, nested functions, etc?

Bem, isso tem tudo a ver, e você vai descobrir logo a seguir!

Meu primeiro Decorator em Python

funções em python - harry potter python

Bem, agora que já temos uma boa noção de funções, e como elas se comportam, nós podemos seguir em nossa jornada com Python Decorators.

Vamos criar um método que executa uma determinada função, e exibe o nome da função antes de executá-la, e depois:


O que você acha que vai acontecer ao executarmos a função minha_func?


Exatamente! Viu como estamos no caminho de alcançar o comportamento que descrevemos que um decorator possui?

Complementar o comportamento de uma determinada função, sem alteramos a função diretamente!

Mesmo Código, Sintaxe Mais Atraente

Bem, apesar do código estranho, nós realmente acabamos de criar o nosso primeiro decorator, avançando mais ainda em nossa jornada nos Python Decorators!

Mas eu concordo, a sintaxe é um tanto estranha, e não aparentam ser o decorator como todos estão acostumados, utilizando o @.

Então vamos lá, você consegue adivinhar neste momento o que precisaremos alterar em nosso código para que possamos utilizar o decorator utilizando a sintaxe com o @?

Exatamente, absolutamente nada! Eu disse, nós já criamos o nosso primeiro decorator!

Quer confirmar?


E pronto, o resultado continua exatamente o mesmo, como queríamos demonstrar!

Reutilizando Decorators

Eu pensei duas ou três vezes antes de escrever isso.

Mas para ficar com a consciência limpa, é melhor falar do que alguém ainda ficar com dúvidas depois de ler este artigo.

Ao criarmos um decorator, ele pode ser utilizado quantas vocês você quiser, em quantas funções diferentes existirem!

Então vamos lá, segue o exemplo:


E como resultado, teremos:

Retornando Valores em Funções Decoradas

Até agora o nosso aprendizado em Python Decorators está ótimo.

Mas imagina que a nossa função retorna algum tipo de valor. O que será que aconteceria com ela se utilizarmos o decorator que nós criamos?!


Agora, você consegue imaginar o resultado que teremos ao executar o código acima?!


Pois é, temos um grande None como retorno de nossa função que está claramente nos retornando um belo Olá!

Como diz o ditado, o diabo mora nos detalhes! Vamos olhar mais de perto a nossa função my_decorator:


Conseguiu achar o problema?!

Nós executamos a função, mas não estamos retornando nenhum valor no decorator. Vamos alterar este pequeno detalhe e executar o código novamente para testarmos a mudança!


E voilá! Temos o nosso resultado esperado!

Seria o meu código Bipolar?

Até agora, nós estamos indo muito bem.

Já aprendemos muita coisa sobre Python Decorators. Mas agora eu vou deixar a seguinte pergunta:

Você sabe quem realmente é quem no seu código?

Nós sabemos que ao acessarmos __name__ dentro da função wrapper de nosso decorator, ele exibe o nome da função corretamente. O que neste caso é: decorado.

Mas e se tentarmos perguntar para a nossa própria função o nome dela?! Será que ela sabe quem ela realmente é?!


Que essa função está pensando que é neste artigo ein?!


Pois é, a tadinha acha que o nome dela é wrapper! Com toda essa história com os nossos Python Decorators, ela até esqueceu quem ela é! Ou será que não?

O que estamos fazendo aqui?

Ao decorarmos uma função, na verdade estamos passando ela como referência para uma outra função, que dentre outras coisas, a executará também! (Pelo menos é o que esperamos de um decorator =D)

Pois bem, que é executado de fato, é a função do nosso decorator, e não a nossa função original!

Vamos dar um remédio para este problema de personalidade da nossa função?!

Então duas doses de wraps. Mas não pode ser genérico ok? Tem que ser do laboratório functools!


E pronto, ao executarmos novamente o nosso código, teremos o seguinte resultado:


Mais um paciente curado pelo super potente remédio @wraps!

Conclusão

Finalizamos mais um artigo falando sobre Python! Muito bom, você não acha?!

Python Decorators são um recurso muito robusto da linguagem Python. Você vai se deparar com vários deles ao trabalhar com frameworks web por exemplo.

Muitos dos frameworks web em Python gostam de utilizar decorators para definir rotas, etc.

E ai, o que você achou do artigo?!

Não se esqueça de deixar a sua opinião nos comentários!

Caso tenha ficado alguma dúvida, não exite em perguntar!

Links Importantes e Referências




Leave a Reply