You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: online/cap12.adoc
+22-7Lines changed: 22 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -75,7 +75,9 @@ Quando um `Vector` tem mais de seis componentes, a string produzida por `repr()`
75
75
`\...`, como visto na última linha do <<ex_vector_demo>>. Isso é fundamental para qualquer tipo de coleção que possa conter um número grande de itens, pois `repr` é usado na depuração—e você não quer que um único objeto grande ocupe milhares de linhas em seu console ou arquivo de log. Use o módulo `reprlib` para produzir representações de tamanho limitado, como no <<ex_vector_v1>>. O módulo `reprlib` se chamava `repr` no Python 2.7.
76
76
====
77
77
78
-
O <<ex_vector_v1>> lista a implementação de nossa primeira versão de `Vector` (esse exemplo usa como base o código mostrado no pass:[<a data-type="xref" href="#ex_vector2d_v0" data-xrefstyle="select: labelnumber">#ex_vector2d_v0</a>] e no pass:[<a data-type="xref" href="#ex_vector2d_v1" data-xrefstyle="select: labelnumber">#ex_vector2d_v1</a>] do <<ch_pythonic_obj>>).
78
+
O <<ex_vector_v1>> lista a implementação de nossa primeira versão de `Vector`
79
+
(esse exemplo usa como base o código mostrado no <<ex_vector2d_v0>> e
80
+
<<ex_vector2d_v1>> do <<ch_pythonic_obj>>).
79
81
80
82
[[ex_vector_v1]]
81
83
.vector_v1.py: derived from vector2d_v1.py
@@ -520,13 +522,12 @@ class Vector:
520
522
# more lines omitted...
521
523
----
522
524
====
523
-
[role="pagebreak-before less_space"]
524
525
<1> Importa `functools` para usar `reduce`.
525
526
<2> Importa `operator` para usar `xor`.
526
527
<3> Não há mudanças em `+__eq__+`; listei-o aqui porque é uma boa prática manter `+__eq__+` e
527
528
`+__hash__+` próximos no código-fonte, pois eles precisam trabalhar juntos.
528
529
<4> Cria uma expressão geradora para computar sob demanda o _hash_ de cada componente.
529
-
<5> Alimenta `reduce` com `hashes` e a função `xor`, para computar o código _hash_ agregado; o terceiro argumento, `0`, é o inicializador (veja o próximo aviso).
530
+
<5> Alimenta `reduce` com `hashes` e a função `xor`, para computar o código _hash_ agregado; o terceiro argumento, `0`, é o inicializador (veja o aviso a seguir).
530
531
531
532
[WARNING]
532
533
====
@@ -585,14 +586,22 @@ Uma forma melhor de comparar um `Vector` com outro `Vector` ou iterável seria o
585
586
return True # <4>
586
587
----
587
588
====
588
-
<1> Se as `len` dos objetos são diferentes, eles não são iguais.
589
-
<2> `zip` produz um gerador de tuplas criadas a partir dos itens em cada argumento iterável. Veja a caixa <<zip_box>>, se `zip` for novidade para você. Em pass:[<img src="callouts/1.png" alt="1"/>], a comparação com `len` é necessária porque `zip` para de produzir valores sem qualquer aviso quando uma das fontes de entrada se exaure.
589
+
<1> Se as `len` dos objetos são diferentes, eles não são iguais. Este teste é importante porque o `zip` encerra a iteração
590
+
assim que o primeiro argumento é consumido.
591
+
<2> `zip` produz um gerador de tuplas criadas a partir dos itens em cada argumento iterável. Veja a caixa <<zip_box>>, se `zip` for novidade para você.
590
592
<3> Sai assim que dois componentes sejam diferentes, devolvendo `False`.
591
593
<4> Caso contrário, os objetos são iguais.
592
594
593
595
[TIP]
594
596
====
595
-
O((("zip() function")))((("functions", "zip() function"))) nome da função `zip` vem de zíper, pois esse objeto físico funciona engatando pares de dentes tomados dos dois lados do zíper, uma boa analogia visual para o que faz `zip(left, right)`. Nenhuma relação com arquivos comprimidos.
597
+
O((("zip() function")))((("functions", "zip() function"))) nome da função `zip` vem de zíper,
598
+
pois esse objeto físico funciona engatando pares de dentes a partir de duas sequências,
599
+
uma boa analogia visual para o que faz `zip(esquerda, direita)`.
600
+
Nenhuma relação com arquivos comprimidos. Por padrão, `zip` para de gerar tuplas assim que um de seus argumentos
601
+
é consumido até o fim, e ele não levanta uma exceção, a menos que o argumento `strict=True` for passado.
602
+
Esse argumento foi introduzido no Python 3.10, mas para preservar a compatibilidade,
603
+
o default é `strict=False`.
604
+
Isto pode causar falhas silenciosas quando um iterável termina antes dos demais.
596
605
====
597
606
598
607
O <<ex_eq_loop>> é eficiente, mas a função `all` pode produzir a mesma computação de um agregado do loop `for` em apenas uma linha:
@@ -751,7 +760,13 @@ O último aperfeiçoamento a `Vector` foi reimplementar o método `+__format__+`
751
760
752
761
Como fizemos no <<ch_pythonic_obj>>, muitas vezes aqui olhamos como os objetos padrão de Python se comportam, para emulá-los e dar a `Vector` uma aparência "pythônica".
753
762
754
-
No <<ch_op_overload>> vamos implemenar vários operadores infixos em `Vector`. A matemática será mais simples que aquela no método `angle()` daqui, mas explorar como os operadores infixos funcionam no Python é uma grande lição sobre design orientado a objetos. Mas antes de chegar à sobrecarga de operadores, vamos parar um pouco de trabalhar com uma única classe e olhar para a organização de múltiplas classes com interfaces e herança, os assuntos dos capítulos pass:[<a data-type="xref" href="#ch_ifaces_prot_abc" data-xrefstyle="select: labelnumber">#ch_ifaces_prot_abc</a>] e pass:[<a data-type="xref" href="ch_inheritance" data-xrefstyle="select: labelnumber">ch_inheritance</a>].
763
+
No <<ch_op_overload>> vamos implemenar vários operadores infixos em `Vector`.
764
+
A matemática será mais simples que aquela no método `angle()` daqui,
765
+
mas explorar como os operadores infixos funcionam no Python
766
+
é uma grande lição sobre design orientado a objetos.
767
+
Mas antes de chegar à sobrecarga de operadores em uma classe,
768
+
vamos estudar a organização de várias classes com interfaces e herança,
769
+
os assuntos dos capítulos <<ch_ifaces_prot_abc>> e <<ch_inheritance>>.
Copy file name to clipboardExpand all lines: online/cap13.adoc
+20-9Lines changed: 20 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -81,7 +81,7 @@ Este((("interfaces", "significant changes to")))((("protocols", "significant cha
81
81
* <<two_kinds_protocols_sec>> explica as semelhanças e diferenças entre protocolos dinâmicos e estáticos.
82
82
* <<defensive_duck_prog_sec>> praticamente reproduz o conteúdo da primeira edição, mas foi atualizada e agora tem um título de seção que enfatiza sua importância.
83
83
* <<static_protocols_sec>> é toda nova. Ela se apoia na apresentação inicial em <<protocols_in_fn_sec>> (<<ch_type_hints_def>>).
84
-
* Os diagramas de classe de `collections.abc` nas Figuras pass:[<a href="#sequence_uml_repeat" data-type="xref" data-xrefstyle="select:labelnumber">#sequence_uml_repeat</a>], pass:[<a href="#mutablesequence_uml" data-type="xref" data-xrefstyle="select:labelnumber">#mutablesequence_uml</a>], and pass:[<a href="#collections_uml" data-type="xref" data-xrefstyle="select:labelnumber">#collections_uml</a>] foram atualizados para incluir a `Collection` ABC, de Python 3.6.
84
+
* Os diagramas de classe de `collections.abc` neste capítulo foram atualizados para incluir a `Collection` ABC, do Python 3.6.
85
85
86
86
A primeira edição de _Python Fluente_ tinha uma seção encorajando o uso das ABCs `numbers` para goose typing.
87
87
Na <<numbers_abc_proto_sec>> eu explico porque, em vez disso, você deve usar protocolos numéricos estáticos do módulo `typing` se você planeja usar checadores de tipos estáticos, ou checagem durante a execução no estilo da goose typing.
@@ -485,7 +485,13 @@ class Lottery:
485
485
def draw(self): ...
486
486
----
487
487
488
-
Obviamente, a mera existência de um método chamado `draw`, chamado sem argumentos, [.keep-together]#está longe# de ser suficiente para garantir que dois objetos `x` e `y`, da forma como `x.draw()` e `y.draw()` podem ser chamados, são de qualquer forma intercambiáveis ou abstratamente pass:[equivalentes —<span class="keep-together"> nada</span>] sobre a similaridade da semântica resultante de tais chamadas pode ser inferido. Na verdade, é necessário um programador inteligente para, de alguma forma, _assegurar_ positivamente que tal equivalência é verdadeira em algum nível.
488
+
Obviamente, a mera existência de um método chamado `draw`, sem parâmetros,
489
+
não é suficiente para garantir que dois objetos `x` e `y`,
490
+
que aceitem as invocações `x.draw()` e `y.draw()`,
491
+
são de qualquer forma intercambiáveis ou abstratamente equivalentes—nada
492
+
pode ser inferido sobre a similaridade da semântica resultante de tais chamadas.
493
+
Na verdade, é necessário um programador inteligente para,
494
+
de alguma forma, _assegurar_ positivamente que tal equivalência é verdadeira em algum nível.
489
495
490
496
Em biologia (e outras disciplinas), este problema levou à emergência (e, em muitas facetas, à dominância) de uma abordagem alternativa à _fenética_, conhecida como ((("cladistics"))) __cladística__ — que baseia as escolhas taxinômicas em características herdadas de ancestrais comuns em vez daquelas que evoluíram de forma independente (o sequenciamento de DNA cada vez mais barato e rápido vem tornando a cladística bastante prática em mais casos).
491
497
@@ -672,8 +678,7 @@ Essa ABC não tem nenhum método próprio, mas foi acrescentada no Python 3.6 pa
672
678
`Sequence`, `Mapping`, `Set`::
673
679
Esses são os principais tipos de coleções imutáveis, e cada um tem uma subclasse mutável.
674
680
Um diagrama detalhado de `MutableSequence` é apresentado em <<mutablesequence_uml>>;
675
-
para `MutableMapping` e `MutableSet`, veja as Figuras pass:[<a data-type="xref" href="#mapping_uml" data-xrefstyle="select: labelnumber">#mapping_uml</a>] e
676
-
pass:[<a data-type="xref" href="#set_uml" data-xrefstyle="select: labelnumber">#set_uml</a>] em <<ch_dicts_sets>>.
681
+
para `MutableMapping` e `MutableSet`, veja a <<mapping_uml>> e a <<set_uml>> em <<ch_dicts_sets>>.
677
682
678
683
`MappingView`::
679
684
No Python 3, os objetos retornados pelos métodos de mapeamentos `.items()`, `.keys()`, e `.values()`
@@ -756,11 +761,14 @@ Os métodos concretos são:
756
761
`.inspect()`:: Retorna uma `tuple` construída a partir dos itens atualmente no container, sem modificar o conteúdo (a ordem interna não é preservada).
757
762
758
763
A <<tombola_uml>> mostra a ABC `Tombola` e três implementações concretas.
764
+
Vale notar que _registered_ (registarada) e _virtual subclass_ (subclasse virtual)
765
+
não são termos da UML padrão, mas representam uma relação de classe específica de Python,
766
+
como veremos na <<virtual_subclass_sec>>.
759
767
760
768
[role="width-80"]
761
769
[[tombola_uml]]
762
-
763
-
.Diagrama UML para uma ABC e três subclasses. O nome da ABC `Tombola` e de seus métodos abstratos estão escritos em _itálico_, segundo as convenções da UML. A seta tracejada é usada para implementações de interface - as estou usando aqui para mostrar que `TomboList` implementa não apenas a interface `Tombola`, mas também está registrada como uma _subclasse virtual_ de `Tombola` - como veremos mais tarde nesse capítulo.pass:[<span data-type="footnote"><span class="roman">«registrada» and «subclasse virtual» não são termos da UML padrão. Estão sendo usados para representar uma relação de classe específica de Python.</span></span>]
770
+
.Diagrama UML para uma ABC e três subclasses. O nome da ABC `Tombola` e de seus métodos abstratos estão escritos em _itálico_, segundo as convenções da UML. A seta tracejada indica que `TomboList` implementa a interface `Tombola`, e também está registrada como _subclasse virtual_.
771
+
`TomboList` também está registrada como uma _subclasse virtual_ de `Tombola`.
764
772
image::../images/flpy_1305.png[UML for Tombola]
765
773
766
774
O <<ex_tombola_abc>> mostra a definição da ABC `Tombola`.
@@ -1861,13 +1869,16 @@ Beazley and Jones's pass:[<em><a class="orm:hideurl" href="https://fpy.li/pycook
1861
1869
tem uma seção sobre como definir uma ABC (Recipe 8.12).
1862
1870
O livro foi escrito antes de Python 3.4,
1863
1871
então eles não usam a atual sintaxe preferida para declarar ABCs, criar uma subclasse de `abc.ABC`
1864
-
(em vez disso, eles usam a palavra-chave `metaclass`, da qual só vamos precisar mesmo em<<ch_class_metaprog>>).
1872
+
(em vez disso, eles usam a palavra-chave `metaclass`, da qual só vamos precisar mesmo em<<ch_class_metaprog>>).
1865
1873
Tirando esse pequeno detalhe, a receita cobre os principais recursos das ABCs muito bem.
1866
1874
1867
1875
_The Python Standard Library by Example_ by Doug Hellmann (Addison-Wesley),
1868
1876
tem um capítulo sobre o módulo `abc`.
1869
-
Ele também esta disponível na web, no excelente site do Doug https://fpy.li/13-51[_PyMOTW_—Python Module of the Week] (EN).
1870
-
Hellmann também usa a declaração de ABC no estilo antigo:`PluginBase(metaclass=abc.ABCMeta)` em vez do mais simples `PluginBase(abc.ABC)`, disponível desde o Python 3.4.
1877
+
Ele também esta disponível na web, em
1878
+
https://fpy.li/13-51[_PyMOTW—Python Module of the Week_].
1879
+
Hellmann usa a declaração de ABC no estilo
1880
+
antigo:`PluginBase(metaclass=abc.ABCMeta)`
1881
+
em vez de `PluginBase(abc.ABC)`, suportada desde o Python 3.4.
1871
1882
1872
1883
Quando usamos ABCs, herança múltipla não é apenas comum mas praticamente inevitável,
1873
1884
porque cada uma das ABCs fundamentais de coleções (`Sequence`, `Mapping`, `Set`)
0 commit comments