def make_bold(fn):
return lambda : "<b>" + fn() + "</b>"
def make_italic(fn):
return lambda : "<i>" + fn() + "</i>"
@make_bold
@make_italic
def hello():
return "hello world"
helloHTML = hello()
Resultado: "<b><i>hello world</i></b>"
Eu entendo aproximadamente sobre decoradores e como funciona com um deles na maioria dos exemplos.
Neste exemplo, existem 2 deles. Pela saída, parece que é @make_italic
executado primeiro, então @make_bold
.
Isso significa que, para funções decoradas, ele primeiro executará a função primeiro e depois avançará para o topo para outros decoradores? Como @make_italic
primeiro então @make_bold
, em vez do contrário.
Então, isso significa que é diferente da norma de abordagem de cima para baixo na maioria das linguagens de programação? Só para esse caso de decorador? Ou eu estou errado?
python
decorator
python-decorators
Novato
fonte
fonte
a(b(x))
é de cima para baixo (se você imaginar que está dividido em 3 linhas)Respostas:
Os decoradores envolvem a função que estão decorando. Assim
make_bold
decorou o resultado domake_italic
decorador, que decorou ahello
função.A
@decorator
sintaxe é apenas um açúcar sintático; Os seguintes:é realmente executado como:
substituindo o
decorated_function
objeto original com o que fordecorator()
retornado.Empilhar decoradores repete esse processo externamente .
Então, sua amostra:
pode ser expandido para:
Quando você chama
hello()
agora, está chamando o objeto retornado pormake_bold()
, na verdade.make_bold()
retornou umlambda
que chama a funçãomake_bold
empacotada, que é o valor de retorno demake_italic()
, que também é um lambda que chama o originalhello()
. Expandindo todas essas ligações que você recebe:então a saída se torna:
fonte
@make_bold #make_bold = make_bold(hello)
@make_italic #make_italic = make_italic (hello)
? Não tenho certeza se com base nisso, envolverá o primeiro resultado. Ou, para este caso de 2 wrappers, o IDE usarámake_bold(make_italic(hello))
como você mencionou em vez do que eu compartilhei?make_bold()
envolve a saída demake_italic()
, que foi usado para envolverhello
, portanto, o equivalente demake_bold(make_italic(hello))
.def inner: return "<b>" + fn() + "</b>"
, entãoreturn inner
seria a versão da função 'regular'; não é uma diferença tão grande.make_italic
decorator é executado antes domake_bold
decorator , porquemake_italic
está mais próximo dodef
. No entanto, esqueço a ordem de execução do código decorado : omake_bold
decorado (isto é, lambda em negrito) é executado primeiro, seguido pelo lambdamake_italic
decorado (isto é, lambda em itálico).