Skip to content

Commit 390b14c

Browse files
committed
vol2: cap 9 e 10: paginação
1 parent 409bd9c commit 390b14c

File tree

8 files changed

+63
-66
lines changed

8 files changed

+63
-66
lines changed

code/10-dp-1class-func/strategy.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
from decimal import Decimal
3434
from typing import Optional, Callable, NamedTuple
3535

36-
3736
class Customer(NamedTuple):
3837
name: str
3938
fidelity: int
@@ -46,6 +45,7 @@ class LineItem(NamedTuple):
4645

4746
def total(self):
4847
return self.price * self.quantity
48+
4949

5050
@dataclass(frozen=True)
5151
class Order: # the Context
@@ -67,10 +67,8 @@ def due(self) -> Decimal:
6767
def __repr__(self):
6868
return f'<Order total: {self.total():.2f} due: {self.due():.2f}>'
6969

70-
7170
# <3>
7271

73-
7472
def fidelity_promo(order: Order) -> Decimal: # <4>
7573
"""5% discount for customers with 1000 or more fidelity points"""
7674
if order.customer.fidelity >= 1000:
@@ -86,13 +84,10 @@ def bulk_item_promo(order: Order) -> Decimal:
8684
discount += item.total() * Decimal('0.1')
8785
return discount
8886

89-
9087
def large_order_promo(order: Order) -> Decimal:
9188
"""7% discount for orders with 10 or more distinct items"""
9289
distinct_items = {item.product for item in order.cart}
9390
if len(distinct_items) >= 10:
9491
return order.total() * Decimal('0.07')
9592
return Decimal(0)
96-
97-
9893
# end::STRATEGY[]

code/10-dp-1class-func/strategy_best4.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,17 +45,14 @@
4545
from strategy import Order
4646

4747
# tag::STRATEGY_BEST4[]
48-
4948
Promotion = Callable[[Order], Decimal]
5049

5150
promos: list[Promotion] = [] # <1>
5251

53-
5452
def promotion(promo: Promotion) -> Promotion: # <2>
5553
promos.append(promo)
5654
return promo
5755

58-
5956
def best_promo(order: Order) -> Decimal:
6057
"""Compute the best discount available"""
6158
return max(promo(order) for promo in promos) # <3>
@@ -68,7 +65,6 @@ def fidelity(order: Order) -> Decimal:
6865
return order.total() * Decimal('0.05')
6966
return Decimal(0)
7067

71-
7268
@promotion
7369
def bulk_item(order: Order) -> Decimal:
7470
"""10% discount for each LineItem with 20 or more units"""
@@ -78,13 +74,11 @@ def bulk_item(order: Order) -> Decimal:
7874
discount += item.total() * Decimal('0.1')
7975
return discount
8076

81-
8277
@promotion
8378
def large_order(order: Order) -> Decimal:
8479
"""7% discount for orders with 10 or more distinct items"""
8580
distinct_items = {item.product for item in order.cart}
8681
if len(distinct_items) >= 10:
8782
return order.total() * Decimal('0.07')
8883
return Decimal(0)
89-
9084
# end::STRATEGY_BEST4[]

online/cap10.adoc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,9 +256,8 @@ include::../code/10-dp-1class-func/strategy.py[tags=STRATEGY_TESTS]
256256
<3> Uma função de promoção diferente é usada aqui e no teste seguinte.
257257

258258

259-
Observe os textos explicativos do <<ex_strategy_tests>>: não há necessidade
260-
de instanciar um novo objeto `promotion` com cada novo pedido:
261-
as funções já estão prontas para usar.
259+
Note que não precisamos criar uma nova instância de `promotion` a
260+
cada novo pedido: as funções já estão prontas para usar.
262261

263262
É interessante notar que no _Padrões de Projetos_, os autores sugerem que:
264263
"Objetos Estratégia muitas vezes são bons "peso mosca"
@@ -418,7 +417,7 @@ startref="FDPrefactor10")))((("", startref="RSfind10")))
418417

419418

420419
[[decorated_strategy_sec]]
421-
=== Estratégia melhorado com decorador
420+
=== Estratégia com decorador de registro
422421

423422
Lembre-se((("functions, design patterns with first-class", "decorator-enhanced
424423
strategy pattern", id="FDPdecorator10")))((("refactoring strategies",

online/cap14.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1239,7 +1239,7 @@ Se você precisar usar subclasses para reutilização de código, então o códi
12391239
ser reutilizado deve estar em métodos mixin de ABCs, ou em classes mixin
12401240
explicitamente nomeadas.
12411241

1242-
Vamos agora analisar o Tkinter do ponto de vista dessas recomendações
1242+
Vamos agora analisar o Tkinter do ponto de vista destas recomendações.
12431243

12441244
==== Tkinter: o bom, o mau e o feio
12451245

vol2/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
## Progresso
44

5-
As primeiras tarefas acontecem nos arquivos `/online/cap??.adoc`.
5+
Faço as primeiras tarefas nos arquivos `/online/cap??.adoc`.
66

7-
Depois cada arquivo é copiado para `/vol?/cap??.adoc`
8-
e as tarefas são feitas nesta cópia para impressão.
7+
Depois copio cada arquivo para `/vol2/cap??.adoc`
8+
e faço as demais tarefas nestas cópias especiais para impressão.
99

1010
| 9 | 10| 11| 12| 13| 14| 15| 16| local | tarefa |
1111
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|-------|-------|
@@ -14,6 +14,6 @@ e as tarefas são feitas nesta cópia para impressão.
1414
|||||||||`/online`|revisar ortografia e gramática|
1515
|||||||||`/vol2`| refazer referências entre volumes|
1616
|||||||||`/vol2`| encurtar links entre volumes |
17-
| | | | | | | | |`/vol2`| exibir capítulo alvo em xrefs para exemplos de outros capítulos |
18-
| | | | | | | | |`/vol2`| rever paginação |
17+
|||||||| |`/vol2`| exibir capítulo alvo em xrefs para exemplos de outros capítulos |
18+
|| | | | | | | |`/vol2`| rever paginação |
1919

vol2/cap09.adoc

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,8 @@ apresento o decorador de _caching_ `functools.cache` do Python
7272
3.9 antes do `functools.lru_cache`, que é mais antigo.
7373
A <<lru_cache_sec>> apresenta também o uso de `lru_cache`
7474
sem argumentos, uma novidade do Python 3.8.
75-
7675
Expandi a <<generic_functions_sec>> para incluir dicas de tipo, a sintaxe
7776
recomendada para usar `functools.singledispatch` desde o Python 3.7.
78-
7977
A <<parameterized_dec_sec>> agora inclui o <<clockdeco_param_cls_ex>>,
8078
que 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
9290
você substituir "função" por "classe" na sentença anterior, o resultado é uma
9391
descrição resumida do papel de um decorador de classe, assunto que veremos no
9492
https://fpy.li/24[«Capítulo 24»] (vol.3).]
95-
9693
Em outras palavras, supondo a existência de uma função decoradora
9794
chamada `decorate`, este código:
9895

@@ -206,6 +203,7 @@ Observe que `register` roda (duas vezes) antes de qualquer outra função no
206203
módulo. Quando `register` é chamada, ela recebe o objeto função a ser decorado
207204
como argumento—por exemplo, `<function f1 at 0x100631bf8>`.
208205

206+
<<<
209207
Após o carregamento do módulo, a lista `registry` contém referências para as
210208
duas funções decoradas: `f1` e `f2`. Essas funções, bem como `f3`, são executadas
211209
apenas quando chamadas explicitamente por `main`.
@@ -250,7 +248,7 @@ argumento. Na prática, a maior parte dos decoradores define e devolve uma funç
250248
interna.
251249

252250
Apesar 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
254252
frameworks Python para adicionar funções a um registro central—por exemplo, um
255253
registro mapeando padrões de URLs para funções que geram respostas HTTP. Tais
256254
decoradores 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

303301
Agora vamos ver um exemplo que pode ser surpreendente.
304302

303+
<<<
305304
Leia com atenção a função `f2`, no <<ex_local_unbound>>. As primeiras duas linhas
306305
sã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
391390
bytecodes de `f1` e `f2`, do <<#ex_global_undef>> e do <<#ex_local_unbound>>,
392391
respectivamente.
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
477477
ao longo de toda a sua história. A cada dia, um novo preço é acrescentado,
478478
e a média é computada levando em conta todos os preços até então.
479479

480+
<<<
480481
Começ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`.
683684
Não tivemos esse problema no <<ex_average_fn>>, porque nunca atribuimos nada ao
684685
nome `series`; apenas chamamos `series.append` e invocamos `sum` e `len` nele.
685686
Nos valemos, então, do fato de listas serem mutáveis.
686-
687687
Mas com tipos imutáveis, como números, strings, tuplas, etc., só é possível ler,
688688
nunca atualizar. Se você reatribuir, como em `count += 1`,
689689
estará 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
746746
chamada.
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

823822
O 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

848847
O decorador `clock` implementado no <<ex_clockdeco0>> tem alguns defeitos: ele
849848
nã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
851852
copiar os atributos relevantes de `func` para `clocked`.
852853
Nesta 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
====
958959
Para((("stacked decorators"))) entender os decoradores empilhados (_stacked decorators_),
@@ -1385,6 +1386,8 @@ revisitar o decorador `clock`, acrescentando um recurso: os usuários podem
13851386
passar uma string para formatar o relatório sobre a função cronometrada.
13861387
Veja 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+
<<<
14541458
Saí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.
15601564
Como exemplos de decoradores parametrizados na biblioteca padrão, visitamos os
15611565
poderosos `@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.
16041608
https://fpy.li/9-11[_Closures in Python_] é um post curto de Fredrik Lundh,
16051609
explicando a terminologia das clausuras.
16061610

1611+
<<<
16071612
A https://fpy.li/9-12[_PEP 3104—Access to Names in Outer Scopes_] (Acesso a Nomes
16081613
em Escopos Externos) descreve a introdução da declaração `nonlocal`.
16091614
Ela 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.
16511656
Se 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
17261733
Desde então, `lambda` é triste apenas devido à sua sintaxe
17271734
limitada.((("", 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
17321742
Os decoradores de função((("Soapbox sidebars", "Python decorators and decorator
@@ -1737,7 +1747,6 @@ criação de subclasses para estender funcionalidade."
17371747
17381748
Ao nível da implementação, os decoradores de Python não lembram o padrão de
17391749
projeto decorador clássico, mas é possível fazer uma analogia.
1740-
17411750
No padrão de projeto, `Decorador` e `Componente` são classes abstratas. Uma
17421751
instância de um decorador concreto envolve uma instância de um componente
17431752
concreto para adicionar comportamentos a ela. Citando _Padrões de Projeto_:
@@ -1753,19 +1762,22 @@ de forma recursiva, possibilitando assim um número ilimitado de
17531762
responsabilidades adicionais. (p. 175 da edição em inglês)
17541763
____
17551764
1765+
17561766
No 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
17581768
função devolvida envolve a função a ser decorada, que é análoga ao componente no
17591769
padrã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
17621772
empilhar decoradores, possibilitando assim um número ilimitado de comportamentos
17631773
adicionais".
17641774
17651775
Veja 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
17671777
situações específicas, mas em geral o padrão decorador é melhor implementado
17681778
com classes representando o decorador e os componentes que ela vai envolver.((("",
17691779
startref="DACsoap09")))
17701780
17711781
****
1782+
1783+
<<<

0 commit comments

Comments
 (0)