Decorando métodos e passando parâmetros nos decorators
Continuação de Decorators em Python - parte 2Decorando Métodos
Em Python, métodos são funções que esperam que seu primeiro parâmetro seja uma referência ao objeto atual. Métodos são funções dentro de classes. Podemos criar decoradores para métodos da mesma maneira que criamos para uma função simples. Vamos usar o p_decorate usado nos nossos exemplos anteriores para decorar uma função que retorna o nome completo de uma pessoa.def p_decorate(func):
def func_wrapper(self):
return "<p>{}</p>".format(func(self))
return func_wrapper
class Pessoa(object):
def __init__(self, nome, sobrenome):
self.nome = nome
self.sobrenome = sobrenome
@p_decorate
def get_nome_completo(self):
return self.nome + " " + self.sobrenome
pessoa = Pessoa('Francisco', 'Lima')
print(pessoa.get_nome_completo())
Passando argumentos nos decoradores
Uma abordagem bem melhor seria tornar nosso decorador útil para funções e métodos. Isso pode ser feito colocando*args e *kwargs como parâmetros para o wrapper, então ele pode aceitar qualquer número arbitrário de argumentos e argumentos de palavras-chave.def p_decorate(func):
def func_wrapper(*args, **kwargs):
return "<p>{0}</p>".format(func(*args, **kwargs))
return func_wrapper
class Pessoa(object):
def __init__(self, nome, sobrenome):
self.nome = nome
self.sobrenome = sobrenome
@p_decorate
def get_nome_completo(self):
return self.nome + " " + self.sobrenome
pessoa = Pessoa('Francisco', 'Lima')
print(pessoa.get_nome_completo())
Vamos ver novamente o exemplo dos 3 decoradores, p, strong e div que usamos na parte 2 deste Post.
def p_decorate(func):
def func_wrapper(nome):
return "<p>{}</p>".format(func(nome))
return func_wrapper
def strong_decorate(func):
def func_wrapper(name):
return "<strong>{0}</strong>".format(func(name))
return func_wrapper
def div_decorate(func):
def func_wrapper(name):
return "<div>{0}</div>".format(func(name))
return func_wrapper
@div_decorate
@p_decorate
@strong_decorate
def get_text(nome):
return "Olá {0}, seja bem vindo ao nosso site!".format(nome)
print (get_text("John"))
Olhando para ele, podemos notar que os 3 decoradores, div_decorate, p_decorate, strong_decorate, são redundantes, cada um possuí basicamente a mesma funcionalidade, apenas envolvendo a string com diferentes tags.
Dá para fazer muito melhor do que isso. Por que não ter uma implementação mais geral para um
decorator que leva a tag para envolver a string? Pois é isso que vamos fazer.def tags(tag_name):
def tags_decorator(func):
def func_wrapper(name):
return "<{0}>{1}</{0}>".format(tag_name, func(name))
return func_wrapper
return tags_decorator
@tags("div")
@tags("p")
@tags("strong")
def get_text(nome):
return "Olá {0}, seja bem vindo ao nosso site!".format(nome)
print(get_text("Francisco"))
Usando um único
decorator, substituimos os 3 anteriores. É claro que tivemos um pouco mais de trabalho neste caso. Os decoradores esperam receber uma função como argumento, e é por isso que tivemos que construir uma função que receba esses argumentos extras para gerar o nosso decorador sobre ela.No exemplo acima,
@tags , é o nosso gerador do decorador.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/
Até...
Francisco ACLima
Nenhum comentário:
Postar um comentário