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: capitulos/cap08.adoc
+41-18Lines changed: 41 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -449,7 +449,7 @@ Por exemplo, não é possível, usando dicas de tipo,
449
449
definir `Quantity` como um número inteiro entre 1 e 10000,
450
450
ou `AirportCode` como uma sequência de 3 letras.
451
451
O NumPy oferece `uint8`, `int16`, e outros tipos numéricos ligados à arquitetura do hardware,
452
-
mas na biblioteca padrão de Python nós encontramos apenas
452
+
mas na biblioteca padrão de Python encontramos apenas
453
453
tipos com conjuntos muitos pequenos de valores (`NoneType`, `bool`)
454
454
ou conjuntos muito grandes (`float`, `int`, `str`, todas as tuplas possíveis, etc.).]
455
455
@@ -876,20 +876,27 @@ Todo sistema de tipagem gradual precisa de um tipo coringa como `Any`
876
876
O verbo "inferir" é um sinônimo bonito para "adivinhar", quando usado no contexto da análise de tipos.
877
877
Verificadores de tipo modernos, em Python e outras linguagens,
878
878
não precisam de anotações de tipo em todo lugar porque conseguem inferir o tipo de muitas expressões.
879
-
Por exemplo, se eu escrever `x = len(s) * 10`, o verificador não precisa de uma declaração local explícita para saber que `x` é um `int`, desde que consiga encontrar dicas de tipo para `len` em algum lugar.
879
+
Por exemplo, se eu escrever `x = len(s) * 10`,
880
+
o verificador não precisa de uma declaração local explícita para saber que `x` é um `int`,
881
+
desde que consiga encontrar dicas de tipo para `len` em algum lugar.
880
882
====
881
883
882
-
Agora podemos explorar o restante dos tipos usados em anotações.((("", startref="GTSsub08")))((("", startref="dynamic08")))((("", startref="anytype08")))
884
+
Agora podemos explorar o restante dos tipos usados em anotações.
Tipos simples((("gradual type system", "simple types and classes"))) como `int`, `float`, `str`, e `bytes` podem ser usados diretamente em dicas de tipo.
887
-
Classes concretas da biblioteca padrão, de pacotes externos ou definidas pelo usuário — `FrenchDeck`, `Vector2d`, e `Duck` - também podem ser usadas em dicas de tipo.
889
+
Tipos simples((("gradual type system", "simple types and classes")))
890
+
como `int`, `float`, `str`, e `bytes` podem ser usados diretamente em dicas de tipo.
891
+
Classes concretas da biblioteca padrão,
892
+
de pacotes externos ou definidas pelo usuário (ex. `FrenchDeck`, `Vector2d`, e `Duck`)
893
+
também podem ser usadas em dicas de tipo.
888
894
889
895
Classes base abstratas também são úteis aqui.
890
896
Voltaremos a elas quando formos estudar os tipos coleção, e em <<type_hint_abc_sec>>.
891
897
892
-
Para classes, _consistente-com_ é definido como _subtipo_de_: uma subclasse é _consistente-com_ todas as suas superclasses.
898
+
Para classes, _consistente-com_ é definido como _subtipo_de_:
899
+
uma subclasse é _consistente-com_ todas as suas superclasses.
893
900
894
901
Entretanto, "a praticidade se sobrepõe à pureza", então há uma exceção importante, discutida em seguida.
895
902
@@ -901,15 +908,17 @@ Não há nenhuma relação nominal de subtipo entre os tipo nativos `int`, `floa
901
908
Mas a PEP 484 https://fpy.li/cardxvi[declara]
902
909
que `int` é _consistente-com_ `float`, e `float` é _consistente-com_ `complex`.
903
910
Na prática, faz sentido:
904
-
`int` implementa todas as operações que `float` implementa, e `int` implementa operações adicionais também - operações binárias como `&`, `|`, `<<`, etc.
911
+
`int` implementa todas as operações que `float` implementa, e `int` implementa operações adicionais também—operações binárias como `&`, `|`, `<<`, etc.
905
912
O resultado final é o seguinte: `int` é _consistente-com_ `complex`.
906
913
Para `i = 3`, `i.real` é `3` e `i.imag` é `0`.
907
914
====
908
915
909
916
910
917
==== Os tipos Optional e Union
911
918
912
-
Nós((("gradual type system", "Optional and Union types")))((("Union type")))((("Optional type"))) vimos o tipo especial `Optional` em <<dealing_with_none_sec>>. Ele resolve o problema de ter `None` como default, como no exemplo daquela seção:
919
+
Vimos((("gradual type system", "Optional and Union types")))((("Union type")))((("Optional type")))
920
+
o tipo especial `Optional` em <<dealing_with_none_sec>>.
921
+
Ele resolve o problema de ter `None` como default, como no exemplo daquela seção:
Um tipo `T` é _consistente-com_ um protocolo `P` se `T` implementa todos os métodos definido em `P`, com assinaturas de tipo correspondentes.
1732
1741
1733
-
Dado `SupportsLessThan`, nós agora podemos definir essa versão funcional de `top` no <<top_protocol_ex>>.
1742
+
Dado `SupportsLessThan`, agora podemos definir essa versão funcional de `top` no <<top_protocol_ex>>.
1734
1743
1735
1744
[[top_protocol_ex]]
1736
1745
._top.py_: definição da função `top` usando uma `TypeVar` com `bound=SupportsLessThan`
@@ -2252,16 +2261,22 @@ Esse é um custo unitário.
2252
2261
2253
2262
Mas há também um custo recorrente, eterno.
2254
2263
2255
-
Nós perdemos um pouco do poder expressivo de Python se insistimos que tudo precisa estar sob a checagem de tipos.
2256
-
Recursos maravilhosos como desempacotamento de argumentos — e.g., `config(**settings)`— estão além da capacidade de compreensão dos checadores de tipos.
2264
+
Perdemos parte do poder expressivo de Python se insistimos que tudo precisa estar sob a checagem de tipos.
2265
+
Recursos excelentes estão além da capacidade de compreensão dos checadores de tipos,
2266
+
por exemplo o desempacotamento de argumentos: `config(**settings)`.
2257
2267
2258
-
Se você quiser ter uma chamada como `config(**settings)` verificada quanto ao tipo, você precisa explicitar cada argumento.
2268
+
Se quiser ter uma chamada como `config(**settings)` verificada quanto ao tipo,
2269
+
precisa explicitar cada argumento.
2259
2270
Isso me traz lembranças de programas em Turbo Pascal, que escrevi 35 anos atrás.
2260
2271
2261
2272
Bibliotecas que usam metaprogramação são difíceis ou impossíveis de anotar.
2262
-
Claro que a metaprogramação pode ser mal usada, mas isso também é algo que torna muitos pacotes de Python divertidos [.keep-together]#de usar#.
2273
+
Claro que a metaprogramação pode ser mal usada,
2274
+
mas isso também é algo que torna muitos pacotes de Python divertidos de usar.
2263
2275
2264
-
Se dicas de tipo se tornarem obrigatórias sem exceções, por uma decisão superior em grande empresas, aposto que logo veremos pessoas usando geração de código para reduzir linhas de código padrão em programas Python - uma prática comum com linguagens menos dinâmicas.
2276
+
Se dicas de tipo se tornarem obrigatórias sem exceções,
2277
+
por uma decisão superior em grande empresas,
2278
+
aposto que logo veremos pessoas usando geração de código para reduzir a verbosidade em programas Python,
2279
+
uma prática comum com linguagens menos dinâmicas.
2265
2280
2266
2281
Para alguns projetos e contextos, dicas de tipo simplesmente não fazem sentido.
2267
2282
Mesmo em contextos onde elas fazer muito sentido, não fazem sentido o tempo todo.
@@ -2271,18 +2286,24 @@ Alan Kay, o recipiente do Turing Award que foi um dos pioneiros da programação
2271
2286
2272
2287
[quote]
2273
2288
____
2274
-
Algumas pessoas são completamente religiosas no que diz respeito a sistemas de tipo, e como um matemático eu adoro a ideia de sistemas de tipos, mas ninguém até agora inventou um que tenha alcance o suficiente..footnote:[Fonte:
2289
+
Algumas pessoas são completamente religiosas no que diz respeito a sistemas de tipo,
2290
+
e como um matemático eu adoro a ideia de sistemas de tipos,
2291
+
mas ninguém até agora inventou um que tenha alcance o suficiente.footnote:[Fonte:
2275
2292
https://fpy.li/8-54["A Conversation with Alan Kay"].]
2276
2293
____
2277
2294
2278
2295
Obrigado, Guido, pela tipagem opcional.
2279
-
Vamos usá-la como foi pensada, e não tentar anotar tudo em conformidade estrita com um estilo de programação que se parece com Java 1.5.((("", startref="SStypehints08")))
2296
+
Vamos usá-la como foi pensada, e não tentar anotar tudo em conformidade estrita com
2297
+
um estilo de programação que se parece com Java 1.5.((("", startref="SStypehints08")))
2280
2298
2281
2299
2282
2300
[role="soapbox-title"]
2283
2301
Duck Typing FTW
2284
2302
2285
-
Duck typing((("Soapbox sidebars", "duck typing")))((("duck typing"))) encaixa bem no meu cérebro, e duck typing estático é um bom compromisso, permitindo checagem estática de tipo sem perder muito da flexibilidade que alguns sistemas de tipagem nominal só permitem ao custo de muita complexidade - isso quando permitem.
encaixa bem no meu cérebro, e duck typing estático é um bom compromisso,
2305
+
permitindo checagem estática de tipo sem perder muito da flexibilidade que
2306
+
alguns sistemas de tipagem nominal só permitem ao custo de muita complexidade - isso quando permitem.
2286
2307
2287
2308
Antes da PEP 544, toda essa ideia de dicas de tipo me parecia completamente não-pythônica,
2288
2309
Fiquei muito feliz quando vi `typing.Protocol` surgir em Python.
@@ -2291,7 +2312,9 @@ Ele traz equilíbrio para a Força.
2291
2312
[role="soapbox-title"]
2292
2313
Genéricos ou Específicos?
2293
2314
2294
-
De((("Soapbox sidebars", "generic collections")))((("generic collections", "Soapbox discussion"))) uma perspectiva de Python, o uso do termo "genérico" na tipagem é um retrocesso.
Copy file name to clipboardExpand all lines: capitulos/cap11.adoc
+6-2Lines changed: 6 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -852,7 +852,7 @@ Quando suportamos a conversão para `bytes`, também implementamos um construtor
852
852
853
853
Vimos que a https://docs.python.org/pt-br/3/library/string.html#formatspec[Mini-Linguagem de Especificação de Formato] é extensível, ao implementarmos um método `+__format__+` que analisa uma `format_spec` fornecida à função embutida `format(obj, format_spec)` ou dentro de campos de substituição `'{:«format_spec»}'` em f-strings ou ainda strings usadas com o método `str.format()`.
854
854
855
-
Para preparar a transformação de instâncias de `Vector2d` em _hashable_, fizemos um esforço para torná-las imutáveis, ao menos prevenindo modificações acidentais, programando os atributos `x` e `y` como privados, e expondo-os como propriedades apenas para leitura. Nós então implementamos
855
+
Para preparar a transformação de instâncias de `Vector2d` em _hashable_, fizemos um esforço para torná-las imutáveis, ao menos prevenindo modificações acidentais, programando os atributos `x` e `y` como privados, e expondo-os como propriedades apenas para leitura. Então implementamos
856
856
`+__hash__+` usando a técnica recomendada, aplicar o operador xor aos _hashes_ dos atributos da instância.
857
857
858
858
Discutimos a seguir a economia de memória e as ressalvas de se declarar um atributo `+__slots__+` em `Vector2d`. Como o uso de `+__slots__+` tem efeitos colaterais, ele só faz real sentido quando é preciso processar um número muito grande de instâncias—pense em milhões de instâncias, não apenas milhares. Em muitos destes casos, usar a https://fpy.li/pandas[pandas] pode ser a melhor opção.
Quando sentimos a necessidade de evitar modificações acidentais dos atributos `x` e `y`, implementamos propriedades, mas nada mudou no restante do código ou na interface pública de `Vector2d`, como se verifica através dos doctests. Continuamos podendo acessar `my_vector.x` and `my_vector.y`.
913
913
914
-
Isso mostra que podemos sempre iniciar o desenvolvimento de nossas classes da maneira mais simples possível, com atributos públicos, pois quando (ou se) nós mais tarde precisarmos impor mais controle, com _getters_ e _setters_, estes métodos podem ser implementados usando propriedades, sem mudar nada no código que já interage com nossos objetos através dos nomes que eram, inicialmente, simples atributos públicos (`x` e `y`, por exemplo).
914
+
Isso mostra que podemos sempre iniciar o desenvolvimento de nossas classes da maneira mais simples possível,
915
+
com atributos públicos, pois quando (ou se) for preciso impor mais depois, com _getters_ e _setters_,
916
+
estes métodos podem ser implementados usando propriedades,
917
+
sem mudar nada no código que já interage com nossos objetos através dos nomes que eram,
918
+
inicialmente, simples atributos públicos (`x` e `y`, por exemplo).
915
919
916
920
Essa abordagem é o oposto daquilo que é encorajado pela linguagem Java: um programador Java não pode começar com atributos públicos simples e apenas mais tarde, se necessário, implementar propriedades, porque elas não existem naquela linguagem. Portanto, escrever _getters_ e _setters_ é a regra em Java—mesmo quando esses métodos não fazem nada de útil—porque a API não pode evoluir de atributos públicos simples para _getters_ e _setters_ sem quebrar todo o código que já use aqueles atributos.
Juntamente com o `+__eq__+` existente, isso tornará as instâncias de `Vector` _hashable_.
437
437
438
438
O `+__hash__+` do `Vector2d` (no <<ex_vector2d_v3_hash>>) computava o _hash_ de uma `tuple` construída com os dois componentes, `self.x` and `self.y`.
439
-
Nós agora podemos estar lidando com milhares de componentes, então criar uma `tuple` pode ser caro demais. Em vez disso, vou aplicar sucessivamente o operador `^` (xor) aos _hashes_ de todos os componentes, assim: `v[0] ^ v[1] ^ v[2]`. É para isso que serve a função `functools.reduce`. Anteriormente afirmei que `reduce` não é mais tão popular quanto antes,footnote:[`sum`, `any`, e `all` cobrem a maioria dos casos de uso comuns de `reduce`. Veja a discussão na <<map_filter_reduce>>.] mas computar o _hash_ de todos os componentes do vetor é um bom caso de uso para ela. A <<reduce_fig>> ilustra a ideia geral da((("reducing functions"))) função `reduce`.
439
+
Agora podemos estar lidando com milhares de componentes, então criar uma `tuple` pode ser caro demais. Em vez disso, vou aplicar sucessivamente o operador `^` (xor) aos _hashes_ de todos os componentes, assim: `v[0] ^ v[1] ^ v[2]`. É para isso que serve a função `functools.reduce`. Anteriormente afirmei que `reduce` não é mais tão popular quanto antes,footnote:[`sum`, `any`, e `all` cobrem a maioria dos casos de uso comuns de `reduce`. Veja a discussão na <<map_filter_reduce>>.] mas computar o _hash_ de todos os componentes do vetor é um bom caso de uso para ela. A <<reduce_fig>> ilustra a ideia geral da((("reducing functions"))) função `reduce`.
440
440
441
441
////
442
442
PROD: unexpected indent in first line after page break
@@ -635,7 +635,7 @@ Ter um loop `for` que itera sobre itens sem perder tempo com variáveis de índi
635
635
----
636
636
====
637
637
<1> `zip` devolve um gerador que produz tuplas sob demanda.
638
-
<2> Cria uma `list` apenas para exibição; nós normalmente iteramos sobre o gerador.
638
+
<2> Cria uma `list` apenas para exibição; normalmente iteramos sobre o gerador.
639
639
<3> `zip` para sem aviso quando um dos iteráveis é exaurido.
640
640
<4> A função `itertools.zip_longest` se comporta de forma diferente: ela usa um `fillvalue` opcional (por default `None`) para preencher os valores ausentes, e assim consegue gerar tuplas até que o último iterável seja exaurido.
0 commit comments