Skip to content

Commit 79b5f39

Browse files
committed
sembreaks
1 parent 8860e30 commit 79b5f39

File tree

1 file changed

+90
-34
lines changed

1 file changed

+90
-34
lines changed

capitulos/cap08.adoc

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -506,14 +506,21 @@ Isso é mais flexível que a _tipagem nominal_, ao preço de permitir mais erros
506506
Tipagem nominal::
507507
É a ((("nominal typing"))) perspectiva adotada em {cpp}, Java, e C#, e suportada em Python anotado.
508508
Objetos e variáveis tem tipos.
509-
Mas objetos só existem durante a execução, e o verificador de tipo só se importa com o código-fonte, onde as variáveis (incluindo parâmetros de função) tem anotações com dicas de tipo.
509+
Mas objetos só existem durante a execução, e o verificador de tipo só se importa com o código-fonte,
510+
onde as variáveis (incluindo parâmetros de função) tem anotações com dicas de tipo.
510511
Se `Duck` é uma subclasse de `Bird`, você pode atribuir uma instância de `Duck` a um parâmetro anotado como `birdie: Bird`.
511-
Mas no corpo da função, o verificador considera a chamada `birdie.quack()` ilegal, pois `birdie` é nominalmente um `Bird`, e aquela classe não fornece o método `.quack()`.
512-
Não interessa que o argumento real, durante a execução, é um `Duck`, porque a tipagem nominal é aplicada de forma estática.
512+
Mas no corpo da função, o verificador considera a chamada `birdie.quack()` ilegal,
513+
pois `birdie` é nominalmente um `Bird`, e aquela classe não fornece o método `.quack()`.
514+
Não interessa que o argumento real, durante a execução, é um `Duck`,
515+
porque a tipagem nominal é aplicada de forma estática.
513516
O verificador de tipo não executa qualquer pedaço do programa, ele apenas lê o código-fonte.
514-
Isso é mais rígido que _duck typing_, com a vantagem de capturar alguns bugs durante o desenvolvimento, ou mesmo em tempo real, enquanto o código está sendo digitado em um IDE.
517+
Isso é mais rígido que _duck typing_,
518+
com a vantagem de capturar alguns bugs durante o desenvolvimento,
519+
ou mesmo em tempo real, enquanto o código está sendo digitado em um IDE.
515520

516-
O <<birds_module_ex>> é um exemplo bobo que contrapõe duck typing e tipagem nominal, bem como checagem de tipos estática e comportamento durante a execução.footnote:[Muitas vezes a herança é sobreutilizada e difícil de justificar em exemplos que, apesar de realistas, são muito simples.
521+
O <<birds_module_ex>> é um exemplo bobo que contrapõe duck typing e tipagem nominal,
522+
bem como checagem de tipos estática e comportamento durante a execução.footnote:[Muitas
523+
vezes a herança é sobreutilizada e difícil de justificar em exemplos pequenos.
517524
Então por favor aceite esse exemplo com animais como uma rápida ilustração de sub-tipagem.]
518525

519526
[[birds_module_ex]]
@@ -538,7 +545,9 @@ birds.py:16: error: "Bird" has no attribute "quack"
538545
Found 1 error in 1 file (checked 1 source file)
539546
----
540547

541-
Só de analisar o código fonte, Mypy percebe que `alert_bird` é problemático: a dica de tipo declara o parâmetro `birdie` como do tipo `Bird`, mas o corpo da função chama `birdie.quack()` — e a classe `Bird` não tem esse método.
548+
Só de analisar o código fonte, Mypy percebe que `alert_bird` é problemático:
549+
a dica de tipo declara o parâmetro `birdie` como do tipo `Bird`,
550+
mas o corpo da função chama `birdie.quack()` — e a classe `Bird` não tem esse método.
542551

543552
Agora vamos tentar usar o módulo `birds` em _daffy.py_ no <<daffy_module_ex>>.
544553

@@ -552,7 +561,8 @@ include::code/08-def-type-hints/birds/daffy.py[]
552561
====
553562
<1> Chamada válida, pois `alert` não tem dicas de tipo.
554563
<2> Chamada válida, pois `alert_duck` recebe um argumento do tipo `Duck` e `daffy` é um `Duck`.
555-
<3> Chamada válida, pois `alert_bird` recebe um argumento do tipo `Bird`, e `daffy` também é um `Bird` — a superclasse de `Duck`.
564+
<3> Chamada válida, pois `alert_bird` recebe um argumento do tipo `Bird`,
565+
e `daffy` também é um `Bird` — a superclasse de `Duck`.
556566

557567
Mypy reporta o mesmo erro em _daffy.py_, sobre a chamada a `quack` na função `alert_bird` definida em _birds.py_:
558568

@@ -580,9 +590,11 @@ Funciona perfeitamente! Viva o duck typing!
580590
Durante a execução do programa, Python não se importa com os tipos declarados.
581591
Ele usa apenas duck typing.
582592
O Mypy apontou um erro em `alert_bird`, mas a chamada da função com `daffy` funciona corretamente quando executada.
583-
À primeira vista isso pode surpreender muitos pythonistas: um verificador de tipo estático muitas vezes encontra erros em código que sabemos que vai funcionar quanto executado.
593+
À primeira vista isso pode surpreender muitos pythonistas:
594+
um verificador de tipo estático muitas vezes encontra erros em código que sabemos que vai funcionar quanto executado.
584595

585-
Entretanto, se daqui a alguns meses você for encarregado de estender o exemplo bobo do pássaro, você agradecerá ao Mypy.
596+
Entretanto, se daqui a alguns meses você for encarregado de estender o exemplo bobo do pássaro,
597+
você agradecerá ao Mypy.
586598
Observe esse módulo _woody.py_ module, que também usa `birds`, no <<woody_module_ex>>.
587599

588600
[[woody_module_ex]]
@@ -606,11 +618,13 @@ Found 2 errors in 2 files (checked 1 source file)
606618
----
607619

608620
O primeiro erro é em _birds.py_: a chamada a `birdie.quack()` em `alert_bird`, que já vimos antes.
609-
O segundo erro é em _woody.py_: `woody` é uma instância de `Bird`, então a chamada `alert_duck(woody)` é inválida, pois aquela função exige um `Duck.`
621+
O segundo erro é em _woody.py_: `woody` é uma instância de `Bird`,
622+
então a chamada `alert_duck(woody)` é inválida, pois aquela função exige um `Duck.`
610623
Todo `Duck` é um `Bird`, mas nem todo `Bird` é um `Duck`.
611624

612625
Durante a execução, nenhuma das duas chamadas em _woody.py_ funcionariam.
613-
A sucessão de falhas é melhor ilustrada em uma sessão no console, através das mensagens de erro, no <<birdie_errors_ex>>.
626+
A sucessão de falhas é melhor ilustrada em uma sessão no console,
627+
através das mensagens de erro, no <<birdie_errors_ex>>.
614628

615629
[[birdie_errors_ex]]
616630
.Erros durante a execução e como o Mypy poderia ter ajudado
@@ -636,34 +650,51 @@ AttributeError: 'Bird' object has no attribute 'quack'
636650
----
637651
====
638652
<1> O Mypy não tinha como detectar esse erro, pois não há dicas de tipo em `alert`.
639-
<2> O Mypy avisou do problema: `Argument 1 to "alert_duck" has incompatible type "Bird"; expected "Duck"` (_Argumento 1 para `alert_duck` é do tipo incompatível "Bird"; argumento esperado era "Duck"_)
640-
<3> O Mypy está avisando desde o <<birds_module_ex>> que o corpo da função `alert_bird` está errado: `"Bird" has no attribute "quack"` (_Bird não tem um atributo "quack"_)
653+
<2> O Mypy avisou do problema: `Argument 1 to "alert_duck" has incompatible type "Bird";
654+
expected "Duck"` (_Argumento 1 para `alert_duck` é do tipo incompatível "Bird"; argumento esperado era "Duck"_)
655+
<3> O Mypy está avisando desde o <<birds_module_ex>> que o corpo da função `alert_bird` está errado:
656+
`"Bird" has no attribute "quack"` (_Bird não tem um atributo "quack"_)
641657

642-
Este pequeno experimento mostra que o duck typing é mais fácil para o iniciante e mais flexível, mas permite que operações não suportadas causem erros durante a execução.
643-
A tipagem nominal detecta os erros antes da execução, mas algumas vezes rejeita código que seria executado sem erros - como a chamada a `alert_bird(daffy)` no <<daffy_module_ex>>.
658+
Este pequeno experimento mostra que o duck typing é mais fácil para o iniciante e mais flexível,
659+
mas permite que operações não suportadas causem erros durante a execução.
660+
A tipagem nominal detecta os erros antes da execução,
661+
mas algumas vezes rejeita código que seria executado sem erros—como
662+
a chamada a `alert_bird(daffy)` no <<daffy_module_ex>>.
644663

645-
Mesmo que funcione algumas vezes, o nome da função `alert_bird` está incorreto: seu código exige um objeto que suporte o método `.quack()`, que não existe em `Bird`.
664+
Mesmo que funcione algumas vezes, o nome da função `alert_bird` está incorreto:
665+
seu código exige um objeto que suporte o método `.quack()`, que não existe em `Bird`.
646666

647667
Nesse exemplo bobo, as funções tem uma linha apenas.
648-
Mas na vida real elas poderiam ser mais longas, e poderiam passar o argumento `birdie` para outras funções, e a origem daquele argumento poderia estar a muitas chamadas de função de distância, tornando difícil localizar a causa do erro durante a execução.
668+
Mas na vida real elas poderiam ser mais longas,
669+
e poderiam passar o argumento `birdie` para outras funções,
670+
e a origem daquele argumento poderia estar a muitas chamadas de função de distância,
671+
tornando difícil localizar a causa do erro durante a execução.
649672
O checador de tipos impede que muitos erros como esse aconteçam durante a execução de um programa.
650673

651674

652675
[NOTE]
653676
====
654677
O valor das dicas de tipo é questionável em exemplos minúsculo que cabem em um livro.
655-
Os benefícios crescem conforme o tamanho da base de código afetada. É por essa razão que empresas com milhões de linhas de código em Python - como a Dropbox, o Google e o Facebook - investiram em equipes e ferramentas para promover a adoção global de dicas de tipo internamente, e hoje tem partes significativas e crescentes de sua base de código checadas para tipo em suas linhas (_pipeline_) de integração contínua.
678+
Os benefícios crescem conforme o tamanho da base de código afetada.
679+
É por essa razão que empresas com milhões de linhas de código em
680+
Python—como Dropbox, Google e Facebook—investiram em equipes e ferramentas para
681+
promover a adoção global de dicas de tipo internamente,
682+
e hoje tem partes significativas e crescentes de sua base de código checadas para tipo em suas linhas (_pipeline_) de integração contínua.
656683
====
657684

658-
Nessa seção exploramos as relações de tipos e operações no duck typing e na tipagem nominal, começando com a função simples `double()` — que deixamos sem dicas de tipo.
685+
Nessa seção exploramos as relações de tipos e operações no duck typing e na tipagem nominal,
686+
começando com a função simples `double()` — que deixamos sem dicas de tipo.
659687
Agora vamos dar uma olhada nos tipos mais importantes ao anotar funções.
660688

661-
Vamos ver um bom modo de adicionar dicas de tipo a `double()` quando examinarmos <<protocols_in_fn>>. Mas antes disso, há tipos mais importantes para conhecer.((("", startref="FTHsupport08")))((("", startref="THsup08")))
689+
Vamos ver um bom modo de adicionar dicas de tipo a `double()` quando examinarmos <<protocols_in_fn>>.
690+
Mas antes disso, há tipos mais importantes para conhecer.((("", startref="FTHsupport08")))((("", startref="THsup08")))
662691

663692

664693
=== Tipos próprios para anotações
665694

666-
Quase((("functions, type hints in", "types usable in annotations", id="FTHusable08")))((("type hints (type annotations)", "types usable in", id="THTusable08"))) todos os tipos em Python podem ser usados em dicas de tipo, mas há restrições e recomendações.
695+
Quase((("functions, type hints in", "types usable in annotations",
696+
id="FTHusable08")))((("type hints (type annotations)", "types usable in", id="THTusable08")))
697+
todos os tipos em Python podem ser usados em dicas de tipo, mas há restrições e recomendações.
667698
Além disso, o((("typing module"))) módulo `typing` introduziu constructos especiais com uma semântica às vezes surpreendente.
668699

669700
Essa seção trata de todos os principais tipos que você pode usar em anotações:
@@ -679,11 +710,14 @@ Essa seção trata de todos os principais tipos que você pode usar em anotaçõ
679710
* `typing.Callable`
680711
* `typing.NoReturn` — um bom modo de encerrar essa lista.
681712

682-
Vamos falar de um de cada vez, começando por um tipo que é estranho, aparentemente inútil, mas de uma importância fundamental.
713+
Vamos falar de um de cada vez, começando por um tipo que é estranho,
714+
aparentemente inútil, mas de uma importância fundamental.
683715

684716
==== O tipo Any
685717

686-
A((("Any type", id="anytype08")))((("dynamic type", id="dynamic08")))((("gradual type system", "Any type", id="GTSany08"))) pedra fundamental de qualquer sistema gradual de tipagem é o tipo `Any`, também conhecido como o _tipo dinâmico_.
718+
A((("Any type", id="anytype08")))((("dynamic type", id="dynamic08")))((("gradual type system", "Any type",
719+
id="GTSany08"))) pedra fundamental de qualquer sistema gradual de tipagem é o tipo `Any`,
720+
também conhecido como o _tipo dinâmico_.
687721
Quando um verificador de tipo vê um função sem tipo como esta:
688722

689723
[source, python]
@@ -699,7 +733,8 @@ def double(x: Any) -> Any:
699733
return x * 2
700734
----
701735

702-
Isso significa que o argumento `x` e o valor de retorno podem ser de qualquer tipo, inclusive de tipos diferentes.
736+
Isso significa que o argumento `x` e o valor de retorno podem ser de qualquer tipo,
737+
inclusive de tipos diferentes.
703738
Assume-se que `Any` pode suportar qualquer operação possível.
704739

705740
Compare `Any` com `object`. Considere essa assinatura:
@@ -731,15 +766,21 @@ que implementa menos operações que `abc.MutableSequence`,
731766
que por sua vez implementa menos operações que `list`.
732767

733768
Mas `Any` é um tipo mágico que reside tanto no topo quanto na base da hierarquia de tipos.
734-
Ele é simultaneamente o tipo mais geral - então um argumento `n: Any` aceita valores de qualquer tipo - e o tipo mais especializado, suportando assim todas as operações possíveis.
769+
Ele é simultaneamente o tipo mais geral - então um argumento `n: Any` aceita valores de
770+
qualquer tipo—e o tipo mais especializado, suportando assim todas as operações possíveis.
735771
Pelo menos é assim que o verificador de tipo entende `Any`.
736772

737-
Claro, nenhum tipo consegue suportar qualquer operação possível, então usar `Any` impede o verificador de tipo de cumprir sua missão primária: detectar operações potencialmente ilegais antes que seu programa falhe e levante uma exceção durante sua execução.((("", startref="GTSany08")))
773+
Claro, nenhum tipo consegue suportar qualquer operação possível,
774+
então usar `Any` impede o verificador de tipo de cumprir sua missão primária:
775+
detectar operações potencialmente ilegais antes que
776+
seu programa levante uma exceção durante a execução.((("", startref="GTSany08")))
738777

739778
[[consistent_with_sec]]
740779
===== Subtipo-de versus consistente-com
741780

742-
Sistemas((("gradual type system", "subtype-of versus consistent-with relationships", id="GTSsub08")))((("subtype-of relationships"))) tradicionais de tipagem nominal orientados a objetos se baseiam na relação _subtipo-de_.
781+
Sistemas((("gradual type system", "subtype-of versus consistent-with relationships",
782+
id="GTSsub08")))((("subtype-of relationships")))
783+
tradicionais de tipagem nominal orientados a objetos se baseiam na relação _subtipo-de_.
743784
Dada uma classe `T1` e uma subclasse `T2`, então `T2` é _subtipo-de_ `T1`.
744785

745786
Observe este código:
@@ -760,11 +801,14 @@ o2 = T2()
760801
f1(o2) # OK
761802
----
762803

763-
A chamada `f1(o2)` é uma aplicação do Princípio de Substituição de Liskov (_Liskov Substitution Principle—LSP_).
804+
A chamada `f1(o2)` é uma aplicação do Princípio de Substituição de Liskov
805+
(_Liskov Substitution Principle—LSP_).
764806

765807
Barbara Liskovfootnote:[Professora do MIT, designer de linguagens de programação e homenageada com o Turing Award em 2008.
766-
Wikipedia: https://pt.wikipedia.org/wiki/Barbara_Liskov[Barbara Liskov].] na verdade definiu _é subtipo-de_ em termos das operações suportadas.
767-
Se um objeto do tipo `T2` substitui um objeto do tipo `T1` e o programa continua se comportando de forma correta, então `T2` é _subtipo-de_ `T1`.
808+
Wikipedia: https://pt.wikipedia.org/wiki/Barbara_Liskov[Barbara Liskov].]
809+
na verdade definiu _é subtipo-de_ em termos das operações suportadas.
810+
Se um objeto do tipo `T2` substitui um objeto do tipo `T1` e
811+
o programa continua se comportando de forma correta, então `T2` é _subtipo-de_ `T1`.
768812

769813
Seguindo com o código visto acima, essa parte mostra uma violação do LSP:
770814

@@ -779,17 +823,28 @@ o1 = T1()
779823
f2(o1) # type error
780824
----
781825

782-
Do ponto de vista das operações suportadas, faz todo sentido: como uma subclasse, `T2` herda e precisa suportar todas as operações suportadas por `T1`. Então uma instância de `T2` pode ser usada em qualquer lugar onde se espera uma instância de `T1`. Mas o contrário não é necessariamente verdadeiro: `T2` pode implementar métodos adicionais, então uma instância de `T1` não pode ser usada onde se espera uma instância de `T2`. Este((("behavioral subtyping"))) foco nas operações suportadas se reflete no nome https://fpy.li/8-15[_behavioral subtyping (subtipagem comportamental)] (EN), também usado para se referir ao LSP.
826+
Do ponto de vista das operações suportadas, faz todo sentido:
827+
como uma subclasse, `T2` herda e precisa suportar todas as operações suportadas por `T1`.
828+
Então uma instância de `T2` pode ser usada em qualquer lugar onde se espera uma instância de `T1`.
829+
Mas o contrário não é necessariamente verdadeiro:
830+
`T2` pode implementar métodos adicionais, então uma instância de `T1`
831+
não pode ser usada onde se espera uma instância de `T2`.
832+
Este((("behavioral subtyping"))) foco nas operações suportadas se reflete no nome
833+
https://fpy.li/8-15[_behavioral subtyping (subtipagem comportamental)] (EN),
834+
também usado para se referir ao LSP.
783835

784-
Em((("consistent-with relationships"))) um sistema de tipagem gradual há outra relação, _consistente-com_ (_consistent-with_), que se aplica sempre que _subtipo-de_ puder ser aplicado, com disposições especiais para o tipo `Any`.
836+
Em((("consistent-with relationships"))) um sistema de tipagem gradual há outra relação,
837+
_consistente-com_ (_consistent-with_),
838+
que se aplica sempre que _subtipo-de_ puder ser aplicado, com regras especiais para o tipo `Any`.
785839

786840
As regras para _consistente-com_ são:
787841

788842
. Dados `T1` e um subtipo `T2`, então `T2` é _consistente-com_ `T1` (substituição de Liskov).
789843
. Todo tipo é _consistente-com_ `Any`: você pode passar objetos de qualquer tipo em um argumento declarado como de tipo `Any.
790844
. `Any` é _consistente-com_ todos os tipos: você sempre pode passar um objeto de tipo `Any` onde um argumento de outro tipo for esperado.
791845

792-
Considerando as definições anteriores dos objetos `o1` e `o2`, aqui estão alguns exemplos de código válido, ilustrando as regras #2 e #3:
846+
Considerando as definições anteriores dos objetos `o1` e `o2`,
847+
aqui estão alguns exemplos de código válido, ilustrando as regras #2 e #3:
793848

794849
[source, python]
795850
----
@@ -819,7 +874,8 @@ Todo sistema de tipagem gradual precisa de um tipo coringa como `Any`
819874
[TIP]
820875
====
821876
O verbo "inferir" é um sinônimo bonito para "adivinhar", quando usado no contexto da análise de tipos.
822-
Verificadores de tipo modernos, em Python e outras linguagens, não precisam de anotações de tipo em todo lugar porque conseguem inferir o tipo de muitas expressões.
877+
Verificadores de tipo modernos, em Python e outras linguagens,
878+
não precisam de anotações de tipo em todo lugar porque conseguem inferir o tipo de muitas expressões.
823879
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.
824880
====
825881

0 commit comments

Comments
 (0)