Criando decorators em python, com exemplos

Thiago Lelis
WhatsGood Dev
Published in
3 min readMar 7, 2022
Imagem contendo algumas linhas de código em python
Imagem: Chris Ried via Unsplash

Decorator é um design pattern que permite que uma funcionalidade seja adicionada a um objeto já existente sem que sua estrutura seja modificada.

Parece um pouco confuso, porém vendo os exemplos abaixo perceberá que é muito simples de ser entendida e poderá facilitar muito quando surgir a necessidade de adicionar novas funcionalidades ao seu código.

Então vamos aos exemplos :)

def mydecorator(function):
def wrapper():
print("Olá, primeiro print")
function()
print("Olá, segundo print")
return wrapper@mydecorator
def hellow():
print("Hello mundo")

hellow()

Analisando o código acima, criamos um decorator chamado mydecorator e dentro do método wrapper temos o trecho do código que desejamos executar do decorator, colocamos dois prints e no meio ficou a function(), no local da function será onde o código do método que receberá o decorator será executado. O código acima irá imprimir no terminal as seguintes linhas:

Olá, primeiro print
Hello mundo
Olá, segundo print

A forma descrita acima é a forma mais básica de se criar um decorator em python, porém caso seja necessário passar um parâmetro para o método que recebe o decorator irá dar um erro, vejo exemplo abaixo

@mydecorator
def hellovar(name):
print(f"Olá {name}")

hellovar("decorador")

Executando o código acima irá receber a seguinte exceção:

Para permitir que o método que está recebendo a anotação (@mydecorator) receba parâmetros precisamos receber estes parâmetros no wrapper dentro do decorator a passar para a function estes mesmo parâmetros. Veja o código abaixo, com atenção para a definição do wrapper recebendo *args e *kwargs.

def mydecorator(function):
def wrapper(*args, **kwargs):
print("Hello my decorator")
return function(*args, **kwargs)
return wrapper
@mydecorator
def hellovar(name):
print(f"Hello {name}")

hellovar("decorator")

O código acima irá imprimir o seguinte texto:

Hello Thiago
Hello my decorator

Até aqui entendemos o básico de como funciona os decorators em python, só com isso conseguimos imaginar como ele poderá ser útil em algumas situações, por exemplo, caso necessite gerar logs das chamadas de seu sistema, ou então calcular o tempo de execução dos métodos, nessas duas situações facilmente poderíamos utilizar os decorator para facilitar nossa vida.

Porém temos algumas situações queremos executar nosso decorator recebendo algum parâmetro, para isso precisamos fazer mais algumas alterações em nosso código, vejamos o exemplo abaixo

def mydecorator(decorator_name):
def decorator_list(function):
def wrapper(*args, **kwargs):
return_function = function(*args, **kwargs)
print(f"Hello my {decorator_name}")
return return_function
return wrapper
return decorator_list
@mydecorator("decorator from var")
def hellovar(name):
print(f"Hello {name}")

hellovar("my decorator")

O código acima irá imprimir o seguinte texto:

Hello my decorator
Hello my decorator from var

Olhando o código acima percebemos que para passar um parâmetro para o nosso decorator precisamos adicionar mais um método dentro do decorator, sendo assim o nome do parâmetro que desejamos vai para a primeira linha, e a function que antes vinha como parâmetro logo na primeira linha passa para o novo método que adicionamos na segunda linha.

Decorator é uma maneira elegante de estender e implementar novas funcionalidades em seu código sem a necessidade de alterar o código atual, com os exemplos mostrados conseguimos cobrir diversas situações corriqueiras do dia a dia que seu uso é interessante, o próprio python utiliza decorators para definição de métodos em classes que não precisam ser instanciados para utilizá-los(@staticmethod e @classmethod) ou o próprio que utiliza decorators dentro de seus models para definir métodos como propriedades (@property ) ou então para definir alguma view do django como login requerido (@login_required).

Decorators é um recurso muito importante para diminuir a duplicação de código e aumentar o reuso de código. No começo o conceito pode parecer um pouco complicado, mas depois de entender o básico do funcionamento, perceberá as grande oportunidades para implementar em seus projetos.

Referências
https://www.python.org/dev/peps/pep-0318/ -> Implementação dos decorators no python 2.4
https://realpython.com/primer-on-python-decorators/#returning-functions-from-functions -> Bom artigo da Real Python (recomendo muito o material deles) também sobre decorators

--

--