Decorators em Python - Parte 1
Essencialmente, os decoradores funcionam como wrappers, modificando o comportamento do código antes e depois da execução de uma função alvo, sem a necessidade de modificar a própria função, aumentando a funcionalidade original, decorando-a.
Mas antes de mergulhar no assunto de @decorators, alguns pontos devem ser explicados. Em Python, funções são cidadãos de primeira classe, são objetos e isso significa que podemos fazer muitas coisas úteis com elas.
Vejamos, por exemplo, as funções abaixo e como elas se comportam.
Mas antes de mergulhar no assunto de @decorators, alguns pontos devem ser explicados. Em Python, funções são cidadãos de primeira classe, são objetos e isso significa que podemos fazer muitas coisas úteis com elas.
Vejamos, por exemplo, as funções abaixo e como elas se comportam.
Uma função pode ser atribuída a uma variável
def cumprimentar(nome):
return "Olá " + nome
cumprimentar_alguem = cumprimentar
print(cumprimentar_alguem("Francisco"))
Uma função pode ser criada dentro de outra
def cumprimentar(nome):
def get_mensagem():
return "Olá "
result = get_mensagem() + nome
return result
print(cumprimentar("Francisco"))
Uma função pode ser passada como parâmetros para outra função
def cumprimentar(nome):
return "Olá " + nome
def testar_funcao(func):
nome = 'Francisco'
return func(nome)
print(testar_funcao(cumprimentar))
Uma função pode retornar outra função
Em outras palavras, funções podem gerar outras funções.def compor_cumprimento():
def get_mensagem():
return "Olá! Tudo bem?"
return get_mensagem
cumprimentar = compor_cumprimento()
print(cumprimentar())
Uma função interna tem acesso a atributos da função envolvente
Uma função interna pode usar atributos da função externa, a função de escopo superior. Assim, mudamos a função get_mensagem() para receber o parâmetronome recebido pela função compor_cumprimento(), retornando get_mensagem().def compor_cumprimento(nome):
def get_mensagem():
return "Olá " + nome + "! Tudo bem?"
return get_mensagem
cumprimentar = compor_cumprimento("Francisco")
print(cumprimentar())
Quando, como no exemplo acima, estão presentes os itens abaixo:
- uma função aninhada (função dentro de uma função)
- a função aninhada usando um valor definido na função de inclusão
- a função de inclusão retornar a função interna, aninhada
Outro ponto é que Python só permite o acesso de leitura ao escopo externo e não atribuição. A não ser que isso seja declarado de forma explícita usando a palavra chave nonlocal (https://www.programiz.com/python-programming/keyword-list#nonlocal).
Compondo nosso primeiro decorador
Usando as ideias acima podemos criar nosso primeiro decorador. Vamos usar uma função que retorna uma frase de bem_vindo() e ampliá-la colocando esse texto numa tag html pdef bem_vindo(nome):
return "Olá {}, seja bem vindo ao nosso site!".format(nome)
print(bem_vindo('Francisco'))
def p_decorate(func):
def func_modificada(nome):
return "<p>{}</p>".format(func(nome))
return func_modificada
my_bem_vindo = p_decorate(bem_vindo)
print(my_bem_vindo("Francisco"))
Esse foi o nosso primeiro decorador. Uma função que recebe outra como argumento, gera uma nova função aumentando o trabalho da função original e retorna a função gerada para que possamos usá-la em qualquer lugar.
Para que bem_vindo() seja decorado por p_decorate() podemos redefini-la passando-a dentro do próprio decorador
def bem_vindo(nome):
return "Olá {}, seja bem vindo ao nosso site!".format(nome)
bem_vindo = p_decorate(bem_vindo)
print(bem_vindo('Francisco'))
Outra observação é que, como nossa função decorada recebe o argumento
"nome", tudo o que precisamos fazer no decorador é permitir que o invólucro de bem_vindo() receba e passe esse argumento para a função original.Sintaxe do decorador em Python
Python torna a criação e o uso de decoradores um agradável para o programador através de um açúcar sintático. Para decorarbem_vindo não temos que usar bem_vindo = p_decorator(bem_vindo). Há um atalho para isso, que é mencionar o nome da função decoradora antes da função a ser decorada com um símbolo @. Neste caso: @p_decorate.def p_decorador(func):
def func_modificada(nome):
return "<p>{}</p>".format(func(nome))
return func_modificada
@p_decorador
def bem_vindo(nome):
return "Olá {}, seja bem vindo ao nosso site!".format(nome)
print(bem_vindo('José'))
Agora sim, nosso "decorator" ficou com uma sintaxe mais interessante.
Jupyter notebook contendo o código deste estudo:
github.com/FranciscoACLima/Python-decorators
Mais sobre o uso de decoradores em Python:
thecodeship.com/patterns/guide-to-python-function-decorators/
Continua em:
Decorators em Python - parte 2
Até...
Francisco ACLima

Nenhum comentário:
Postar um comentário