@@ -72,10 +72,8 @@ apresento o decorador de _caching_ `functools.cache` do Python
72723.9 antes do `functools.lru_cache`, que é mais antigo.
7373A <<lru_cache_sec>> apresenta também o uso de `lru_cache`
7474sem argumentos, uma novidade do Python 3.8.
75-
7675Expandi a <<generic_functions_sec>> para incluir dicas de tipo, a sintaxe
7776recomendada para usar `functools.singledispatch` desde o Python 3.7.
78-
7977A <<parameterized_dec_sec>> agora inclui o <<clockdeco_param_cls_ex>>,
8078que usa uma classe e não uma clausura para implementar um decorador.
8179
@@ -92,7 +90,6 @@ devolver a mesma função ou substituí-la por outra função ou objeto invocáv
9290você substituir "função" por "classe" na sentença anterior, o resultado é uma
9391descrição resumida do papel de um decorador de classe, assunto que veremos no
9492https://fpy.li/24[«Capítulo 24»] (vol.3).]
95-
9693Em outras palavras, supondo a existência de uma função decoradora
9794chamada `decorate`, este código:
9895
@@ -206,6 +203,7 @@ Observe que `register` roda (duas vezes) antes de qualquer outra função no
206203módulo. Quando `register` é chamada, ela recebe o objeto função a ser decorado
207204como argumento—por exemplo, `<function f1 at 0x100631bf8>`.
208205
206+ <<<
209207Após o carregamento do módulo, a lista `registry` contém referências para as
210208duas funções decoradas: `f1` e `f2`. Essas funções, bem como `f3`, são executadas
211209apenas quando chamadas explicitamente por `main`.
@@ -250,7 +248,7 @@ argumento. Na prática, a maior parte dos decoradores define e devolve uma funç
250248interna.
251249
252250Apesar do decorador `register` no <<registration_ex>> devolver a função decorada
253- inalterada, esta técnica não é inútil. Decoradores parecidos são usados por muitos
251+ inalterada, ele não é inútil. Decoradores parecidos são usados por muitos
254252frameworks Python para adicionar funções a um registro central—por exemplo, um
255253registro mapeando padrões de URLs para funções que geram respostas HTTP. Tais
256254decoradores de registro podem ou não modificar as funções decoradas.
@@ -302,6 +300,7 @@ atribuirmos um valor a um `b` global e então chamarmos `f1`, funciona:
302300
303301Agora vamos ver um exemplo que pode ser surpreendente.
304302
303+ <<<
305304Leia com atenção a função `f2`, no <<ex_local_unbound>>. As primeiras duas linhas
306305são as mesmas da `f1` do <<ex_global_undef>>, e então ela faz uma atribuição a
307306`b`. Mas para com um erro no segundo `print`, antes da atribuição ser executada.
@@ -391,6 +390,7 @@ Leia no <<#ex_f1_dis>> e no <<#ex_f2_dis>> os
391390bytecodes de `f1` e `f2`, do <<#ex_global_undef>> e do <<#ex_local_unbound>>,
392391respectivamente.
393392
393+ <<<
394394[[ex_f1_dis]]
395395.Bytecode da função `f1` do <<ex_global_undef>>
396396====
@@ -477,6 +477,7 @@ cresce continuamente; por exemplo, o preço diário de um produto
477477ao longo de toda a sua história. A cada dia, um novo preço é acrescentado,
478478e a média é computada levando em conta todos os preços até então.
479479
480+ <<<
480481Começando do zero, `avg` poderia ser usada assim:
481482
482483[source, python]
@@ -683,7 +684,6 @@ e isso a torna uma variável local. O mesmo problema afeta a variável `total`.
683684Não tivemos esse problema no <<ex_average_fn>>, porque nunca atribuimos nada ao
684685nome `series`; apenas chamamos `series.append` e invocamos `sum` e `len` nele.
685686Nos valemos, então, do fato de listas serem mutáveis.
686-
687687Mas com tipos imutáveis, como números, strings, tuplas, etc., só é possível ler,
688688nunca atualizar. Se você reatribuir, como em `count += 1`,
689689estará implicitamente criando uma variável local `count`. Ela não será mais uma
@@ -746,7 +746,7 @@ decorada e exibe o tempo decorrido, os argumentos passados, e o resultado da
746746chamada.
747747
748748[[ex_clockdeco0]]
749- ._clockdeco0.py_: decorador simples que mostra o tempo de execução de funções
749+ ._clockdeco0.py_: decorador que exibe o tempo de execução da função
750750====
751751[source, python]
752752----
@@ -817,7 +817,6 @@ dos panos). De fato, se você importar o módulo `clockdeco_demo` e verificar o
817817>>> import clockdeco_demo
818818>>> clockdeco_demo.factorial.__name__
819819'clocked'
820- >>>
821820----
822821
823822O nome `factorial` agora é uma referência para a função `clocked`. Daqui por
@@ -847,10 +846,13 @@ No _<<closures_soapbox>>_ escrevi mais sobre esse assunto.
847846
848847O decorador `clock` implementado no <<ex_clockdeco0>> tem alguns defeitos: ele
849848não aceita argumentos nomeados, e encobre o `+__name__+` e o `+__doc__+` da
850- função decorada. O <<ex_clockdeco2>> usa o decorador `functools.wraps` para
849+ função decorada.
850+
851+ O <<ex_clockdeco2>> usa o decorador `functools.wraps` para
851852copiar os atributos relevantes de `func` para `clocked`.
852853Nesta nova versão, os argumentos nomeados também são tratados corretamente.
853854
855+ <<<
854856[[ex_clockdeco2]]
855857._clockdeco.py_: um decorador `clock` melhorado
856858====
@@ -952,7 +954,6 @@ Veja a <<lru_cache_sec>> para uma alternativa que suporta versões anteriores de
952954`@cache` é aplicado à função devolvida por `@clock`.
953955
954956[[stacked_decorators_tip]]
955- .Decoradores empilhados
956957[TIP]
957958====
958959Para((("stacked decorators"))) entender os decoradores empilhados (_stacked decorators_),
@@ -1385,6 +1386,8 @@ revisitar o decorador `clock`, acrescentando um recurso: os usuários podem
13851386passar uma string para formatar o relatório sobre a função cronometrada.
13861387Veja o <<clockdeco_param_ex>>.
13871388
1389+
1390+ <<<
13881391[NOTE]
13891392====
13901393
@@ -1451,6 +1454,7 @@ include::../code/09-closure-deco/clock/clockdeco_param_demo1.py[]
14511454----
14521455====
14531456
1457+ <<<
14541458Saída do <<ex_clockdecoparam_demo1>>:
14551459
14561460[source]
@@ -1494,7 +1498,7 @@ de Graham Dumpleton e o módulo `wrapt`.
14941498
14951499====
14961500
1497- A próxima seção traz um exemplo no estilo recomendado por Regebro e Dumpleton.((("", startref="CDparam09")))
1501+ Agora veremos um exemplo no estilo recomendado por Regebro e Dumpleton.((("", startref="CDparam09")))
14981502
14991503==== Um decorador de cronometragem em forma de classe
15001504
@@ -1560,7 +1564,7 @@ baseada em classes pode ser mais fácil de ler e manter.
15601564Como exemplos de decoradores parametrizados na biblioteca padrão, visitamos os
15611565poderosos `@cache` e `@singledispatch`, do módulo `functools`.
15621566
1563-
1567+ <<<
15641568[[decorator_further]]
15651569=== Para saber mais
15661570
@@ -1604,6 +1608,7 @@ ela ainda é uma excelente fonte de inspiração.
16041608https://fpy.li/9-11[_Closures in Python_] é um post curto de Fredrik Lundh,
16051609explicando a terminologia das clausuras.
16061610
1611+ <<<
16071612A https://fpy.li/9-12[_PEP 3104—Access to Names in Outer Scopes_] (Acesso a Nomes
16081613em Escopos Externos) descreve a introdução da declaração `nonlocal`.
16091614Ela também inclui uma excelente revisão de como essa questão foi resolvida
@@ -1651,6 +1656,8 @@ do ambiente onde a função é invocada.
16511656Se Python tivesse escopo dinâmico e não tivesse clausuras, poderíamos improvisar
16521657`avg` (similar ao <<ex_average_fn>>) desta forma:
16531658
1659+ <<<
1660+
16541661[source, python]
16551662----
16561663>>> ### esta não é uma sessão real de Python! ###
@@ -1726,7 +1733,10 @@ Isso foi resolvido no Python 2.2 (de dezembro de 2001), mas a blogosfera nunca p
17261733Desde então, `lambda` é triste apenas devido à sua sintaxe
17271734limitada.((("", startref="Scynamic09")))((("", startref="SSdynamic09")))
17281735
1729- [role="soapbox-title"]
1736+ ****
1737+ <<<
1738+
1739+ ****
17301740**Os decoradores de Python e o padrão de projeto Decorator**
17311741
17321742Os decoradores de função((("Soapbox sidebars", "Python decorators and decorator
@@ -1737,7 +1747,6 @@ criação de subclasses para estender funcionalidade."
17371747
17381748Ao nível da implementação, os decoradores de Python não lembram o padrão de
17391749projeto decorador clássico, mas é possível fazer uma analogia.
1740-
17411750No padrão de projeto, `Decorador` e `Componente` são classes abstratas. Uma
17421751instância de um decorador concreto envolve uma instância de um componente
17431752concreto para adicionar comportamentos a ela. Citando _Padrões de Projeto_:
@@ -1753,19 +1762,22 @@ de forma recursiva, possibilitando assim um número ilimitado de
17531762responsabilidades adicionais. (p. 175 da edição em inglês)
17541763____
17551764
1765+
17561766No Python, a função decoradora faz o papel de uma subclasse concreta de
17571767`Decorador`, e a função interna que ela devolve é uma instância do decorador. A
17581768função devolvida envolve a função a ser decorada, que é análoga ao componente no
17591769padrão de projeto. A função devolvida é transparente, pois se adapta à interface
1760- do componente (ao aceitar os mesmos argumentos). Pegando emprestado da citação
1761- anterior, podemos adaptar a última frase para dizer que "A transparência permite
1770+ do componente (ao aceitar os mesmos argumentos). Adaptando a última frase
1771+ da citação: "A transparência permite
17621772empilhar decoradores, possibilitando assim um número ilimitado de comportamentos
17631773adicionais".
17641774
17651775Veja que não estou sugerindo que decoradores de função devam ser usados para
1766- implementar o padrão decorador em programas Python. Pode até ser possível em
1776+ implementar o padrão decorador em programas Python. Pode até ser feito em
17671777situações específicas, mas em geral o padrão decorador é melhor implementado
17681778com classes representando o decorador e os componentes que ela vai envolver.((("",
17691779startref="DACsoap09")))
17701780
17711781****
1782+
1783+ <<<
0 commit comments