33:example-number: 0
44:figure-number: 0
55
6- [quote, PEP 318—Decorators for Functions and Methods ("Decoradores para Funções e Métodos"—EN) ]
6+ [quote, PEP 318—Decorators for Functions and Methods]
77____
88Houve uma certa quantidade de reclamações sobre a escolha do nome "decorador"
99para esse recurso. A mais frequente foi sobre o nome não ser consistente com seu
1010uso no livro da GoF.footnote:[GoF se refere ao livro __Design Patterns__
11- (traduzido no Brasil como _" Padrões de Projeto"_), de 1985 . Seus quatro
12- autores ficaram conhecidos como a "Gang of Four" (_Gangue dos Quatro_ ).] O nome
11+ (traduzido no Brasil como Padrões de Projeto) . Seus
12+ autores ficaram conhecidos como a _Gang of Four_ (Gangue dos Quatro ).] O nome
1313++decorator++ provavelmente se origina de seu uso no âmbito dos
1414compiladores--uma árvore sintática é percorrida e anotada.
1515____
@@ -53,6 +53,7 @@ capítulo é explicar exatamente como funcionam os decoradores de função, desd
5353simples decoradores de registro até os complicados decoradores parametrizados.
5454Mas antes de chegar a esse objetivo, precisamos tratar de:
5555
56+ <<<
5657* Como Python analisa a sintaxe de decoradores
5758* Como Python decide se uma variável é local
5859* Por que clausuras existem e como elas funcionam
@@ -72,7 +73,7 @@ apresento o decorador de _caching_ `functools.cache` do Python
72733.9 antes do `functools.lru_cache`, que é mais antigo.
7374A <<lru_cache_sec>> apresenta também o uso de `lru_cache`
7475sem argumentos, uma novidade do Python 3.8.
75- Expandi a <<generic_functions_sec >> para incluir dicas de tipo, a sintaxe
76+ Expandi a <<single_dispatch_sec >> para incluir dicas de tipo, a sintaxe
7677recomendada para usar `functools.singledispatch` desde o Python 3.7.
7778A <<parameterized_dec_sec>> agora inclui o <<clockdeco_param_cls_ex>>,
7879que usa uma classe e não uma clausura para implementar um decorador.
@@ -90,9 +91,11 @@ devolver a mesma função ou substituí-la por outra função ou objeto invocáv
9091você substituir "função" por "classe" na sentença anterior, o resultado é uma
9192descrição resumida do papel de um decorador de classe, assunto que veremos no
9293https://fpy.li/24[«Capítulo 24»] (vol.3).]
94+
9395Em outras palavras, supondo a existência de uma função decoradora
9496chamada `decorate`, este código:
9597
98+ <<<
9699[source, python]
97100----
98101@decorate
@@ -143,7 +146,6 @@ running inner()
143146<3> Invocar a `target` decorada causa, na verdade, a execução de `inner`.
144147<4> A inspeção revela que `target` é agora uma referência a `inner`.
145148
146-
147149Estritamente falando, decoradores são apenas açúcar sintático. Como vimos, é
148150sempre possível chamar um decorador como um invocável normal, passando outra
149151função como parâmetro. Algumas vezes isso inclusive é conveniente, especialmente
@@ -203,7 +205,6 @@ Observe que `register` roda (duas vezes) antes de qualquer outra função no
203205módulo. Quando `register` é chamada, ela recebe o objeto função a ser decorado
204206como argumento—por exemplo, `<function f1 at 0x100631bf8>`.
205207
206- <<<
207208Após o carregamento do módulo, a lista `registry` contém referências para as
208209duas funções decoradas: `f1` e `f2`. Essas funções, bem como `f3`, são executadas
209210apenas quando chamadas explicitamente por `main`.
@@ -300,7 +301,6 @@ atribuirmos um valor a um `b` global e então chamarmos `f1`, funciona:
300301
301302Agora vamos ver um exemplo que pode ser surpreendente.
302303
303- <<<
304304Leia com atenção a função `f2`, no <<ex_local_unbound>>. As primeiras duas linhas
305305são as mesmas da `f1` do <<ex_global_undef>>, e então ela faz uma atribuição a
306306`b`. Mas para com um erro no segundo `print`, antes da atribuição ser executada.
@@ -369,11 +369,11 @@ Nos exemplos anteriores, vimos dois escopos em ação:
369369O escopo global do módulo:: Composto((("scope", "module global scope"))) por
370370nomes atribuídos a valores fora de qualquer bloco de classe ou função.
371371
372- O escopo local da função f3 :: Composto((("scope", "function local scope"))) por
372+ O escopo local da função `f3` :: Composto((("scope", "function local scope"))) por
373373nomes atribuídos a valores como parâmetros, ou diretamente no corpo da função.
374374
375- Há um outro escopo de onde variáveis podem vir , chamado _nonlocal_, e ele é
376- fundamental para clausuras ; vamos tratar disso em breve.
375+ Há um outro escopo onde variáveis podem existir , chamado _nonlocal_ (não-local).
376+ Ele ocorre quando há funções aninhadas ; vamos tratar disso em breve.
377377
378378Agora que vimos como o escopo de variáveis funciona no Python, podemos
379379enfrentar as clausuras na <<closures_sec>>.
@@ -455,17 +455,17 @@ https://fpy.li/5x["dis—Disassembler de bytecode de Python"].
455455=== Clausuras
456456
457457Na((("decorators and closures", "closure basics", id="DACclos09")))((("anonymous
458- functions"))) blogosfera, as clausuras são algumas vezes confundidas com funções
459- anônimas. Muita gente confunde por causa da história paralela destes conceitos:
458+ functions"))) blogosfera, as clausuras (_closures_) são às vezes confundidas com funções
459+ anônimas. A confusão se deve à história paralela destes conceitos:
460460definir funções dentro de outras funções se torna mais comum e conveniente quando
461461existem funções anônimas.
462462E clausuras só fazem sentido a partir do momento em que você tem funções aninhadas.
463463Daí que muitos aprendem as duas ideias ao mesmo tempo.
464464
465465Na verdade, uma clausura é uma função—vamos chamá-la de `f`—com um escopo
466- estendido, incorporando variáveis acessadas no corpo de `f` que não são nem
466+ estendido, incorporando variáveis acessadas no corpo de `f` que não são
467467variáveis globais nem variáveis locais de `f`. Tais variáveis devem vir do
468- escopo local de uma função externa que englobe `f`.
468+ escopo local de uma função que engloba `f`.
469469
470470Não interessa se a função é anônima ou não; o que importa é que ela pode
471471acessar variáveis não-globais definidas fora de seu corpo.
@@ -605,17 +605,15 @@ que representa o corpo compilado da função. O <<ex_average_demo2>> demonstra i
605605====
606606
607607O valor de `series` é armazenado no atributo `+__closure__+` da função
608- `avg`. Cada item em `+avg.__closure__+` corresponde a um nome em `+__code__+`.
609- Esses itens são `cells`, e têm um atributo chamado `cell_contents`, onde o valor
610- real pode ser encontrado. O <<ex_average_demo3>> mostra esses atributos.
608+ `avg`. Cada item em `+avg.__closure__+` corresponde a um nome em `+__code__+`,
609+ e tem um atributo chamado `cell_contents`, com o valor vinculado.
610+ Confira o <<ex_average_demo3>>:
611611
612612[[ex_average_demo3]]
613613.Continuando do <<ex_average_demo1>>
614614====
615615[source, python]
616616----
617- >>> avg.__code__.co_freevars
618- ('series',)
619617>>> avg.__closure__
620618(<cell at 0x107a44f78: list object at 0x107a91a48>,)
621619>>> avg.__closure__[0].cell_contents
@@ -633,7 +631,7 @@ aquelas variáveis sejam parte do escopo local da função externa.((("",
633631startref="DACclos09")))
634632
635633[[nonlocal_sec]]
636- === A declaração nonlocal
634+ === A instrução ` nonlocal`
637635
638636A((("decorators and closures", "nonlocal declarations",
639637id="DACnonlocal09")))((("nonlocal keyword", id="nonlocal09")))((("keywords",
@@ -666,6 +664,8 @@ def make_averager():
666664
667665Ao testar o <<ex_average_broken>>, o resultado é um erro:
668666
667+ <<<
668+
669669[source, python]
670670----
671671>>> avg = make_averager()
@@ -745,6 +745,8 @@ id="DACdecimp09"))) um decorador que cronometra cada invocação da função
745745decorada e exibe o tempo decorrido, os argumentos passados, e o resultado da
746746chamada.
747747
748+ <<<
749+
748750[[ex_clockdeco0]]
749751._clockdeco0.py_: decorador que exibe o tempo de execução da função
750752====
@@ -880,7 +882,7 @@ interessantes da biblioteca padrão são `cache`, `lru_cache` e
880882`singledispatch`—todos do módulo `functools`. Falaremos deles a seguir.
881883
882884[[memoization_sec]]
883- ==== Memoização com functools.cache
885+ ==== Memoização com ` functools.cache`
884886
885887O((("memoization", id="memoiz09")))((("functools module", "functools.cache
886888decorator", id="functool09"))) decorador `functools.cache` implementa
@@ -1023,7 +1025,7 @@ startref="memoiz09")))((("", startref="functool09")))
10231025
10241026
10251027[[lru_cache_sec]]
1026- ==== Usando o lru_cache
1028+ ==== Usando o `functools. lru_cache`
10271029
10281030O((("functools module", "functools.lru_cache function"))) decorador
10291031`functools.cache` é, na realidade, um mero invólucro em torno da antiga função
@@ -1089,7 +1091,7 @@ def costly_function(a, b):
10891091
10901092Vamos agora examinar outro decorador poderoso: `functools.singledispatch`.
10911093
1092- [[generic_functions_sec ]]
1094+ [[single_dispatch_sec ]]
10931095==== Funções genéricas com despacho único
10941096
10951097Imagine((("single dispatch generic functions",
@@ -1146,9 +1148,6 @@ e a sequência inteira é apresentada como uma lista HTML.
11461148<6> Mostra `Fraction` como uma fração.
11471149<7> Mostra `float` e `Decimal` com a fração equivalente aproximada.
11481150
1149- [[single_dispatch_sec]]
1150- ===== Despacho único de funções
1151-
11521151Como não temos no Python a sobrecarga de métodos ao estilo de Java, não podemos
11531152simplesmente criar variações de `htmlize` com assinaturas diferentes para cada
11541153tipo de dado que queremos tratar de forma distinta. Uma solução possível em
@@ -1170,7 +1169,7 @@ Se mais argumentos fossem usados para selecionar a função específica,
11701169teríamos despacho múltiplo (_multiple dispatch_), um recurso nativo em
11711170linguagens como Common Lisp, Julia e C#.
11721171
1173- O <<singledispatch_ex>> mostra como funciona o despacho único.
1172+ O <<singledispatch_ex>> mostra como implementar o despacho único.
11741173
11751174[WARNING]
11761175====
@@ -1386,18 +1385,16 @@ revisitar o decorador `clock`, acrescentando um recurso: os usuários podem
13861385passar uma string para formatar o relatório sobre a função cronometrada.
13871386Veja o <<clockdeco_param_ex>>.
13881387
1389-
1390- <<<
13911388[NOTE]
13921389====
1393-
13941390Para simplificar, o <<clockdeco_param_ex>> está baseado na implementação inicial
13951391de `clock` no <<ex_clockdeco0>>, e não na versão melhorada do
1396- <<ex_clockdeco2>> que usa `@functools.wraps`, acrescentando assim mais uma
1397- camada de função.
1398-
1392+ <<ex_clockdeco2>> que usa `@functools.wraps`,
1393+ evitando mais um nível de aninhamento de funções.
13991394====
14001395
1396+ <<<
1397+
14011398[[clockdeco_param_ex]]
14021399.Módulo clockdeco_param.py: o decorador `clock` parametrizado
14031400====
@@ -1572,8 +1569,8 @@ O((("decorators and closures", "further reading on"))) item #26 do livro
15721569https://fpy.li/effectpy[_Effective Python_, 2nd ed.] (Addison-Wesley), de
15731570Brett Slatkin, trata das melhores práticas para decoradores de função, e
15741571recomenda sempre usar `functools.wraps`—que vimos no
1575- <<ex_clockdeco2>>.footnote:[ Como queria manter o código o mais simples possível,
1576- não segui o excelente conselho de Slatkin em todos os exemplos.]
1572+ <<ex_clockdeco2>>. Como eu queria manter o código o mais simples possível,
1573+ não segui o excelente conselho de Slatkin em todos os exemplos.
15771574
15781575Graham Dumpleton tem, em seu blog, uma https://fpy.li/9-5[série de posts
15791576abrangentes] sobre técnicas para implementar decoradores bem comportados,
@@ -1586,13 +1583,13 @@ que suportam introspecção e se comportam de forma correta quando decorados
15861583novamente, quando aplicados a métodos e quando usados como descritores de
15871584atributos (o https://fpy.li/23[«Capítulo 23»] (vol.3) é sobre descritores).
15881585
1589- https://fpy.li/9-8["Metaprogramming" (_Metaprogramação_)] (EN) , o capítulo 9 do
1586+ https://fpy.li/9-8[_Metaprogramming_] , o capítulo 9 do
15901587_Python Cookbook_, 3ª ed. de David Beazley e Brian K. Jones (O'Reilly), tem
15911588várias receitas ilustrando desde decoradores elementares até alguns muito
15921589sofisticados, incluindo um que pode ser invocado como um decorador regular ou
15931590como uma fábrica de decoradores, por exemplo, `@clock` ou `@clock()`. É a
1594- "Recipe 9.6. Defining a Decorator That Takes an Optional Argument" (_Receita
1595- 9.6. Definindo um Decorador Que Recebe um Argumento Opcional_) desse livro de
1591+ _Recipe 9.6. Defining a Decorator That Takes an Optional Argument_
1592+ ( Definindo um Decorador Que Recebe um Argumento Opcional) daquele livro de
15961593receitas.
15971594
15981595Michele Simionato criou https://fpy.li/9-9[_decorator_],
@@ -1626,7 +1623,7 @@ A https://fpy.li/9-14[_PEP 443_] traz a justificativa e uma descrição
16261623detalhada do mecanismo de funções genéricas de despacho único. Um post de Guido
16271624van Rossum de março de 2005
16281625https://fpy.li/9-15[_Five-Minute Multimethods in Python_]
1629- (Multi-métodos de cinco minutos em Python_ ), mostra os passos
1626+ (Multi-métodos de cinco minutos em Python ), mostra os passos
16301627para uma implementação de funções genéricas (também chamadas multi-métodos)
16311628usando decoradores. O código de multi-métodos de Guido é interessante, mas é
16321629apenas um exemplo didático. Para conhecer uma implementação de funções genéricas
0 commit comments