Skip to content

Commit fb4e121

Browse files
committed
cap14: revisão de estilo
1 parent d40b2c6 commit fb4e121

File tree

3 files changed

+93
-61
lines changed

3 files changed

+93
-61
lines changed
File renamed without changes.

online/cap09.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ A <<lru_cache_sec>> apresenta também o uso de `lru_cache`
7474
sem argumentos, uma novidade do Python 3.8.
7575

7676
Expandi a <<generic_functions_sec>> para incluir dicas de tipo, a sintaxe
77-
recomendada de usar `functools.singledispatch` desde o Python 3.7.
77+
recomendada para usar `functools.singledispatch` desde o Python 3.7.
7878

7979
A <<parameterized_dec_sec>> agora inclui o <<clockdeco_param_cls_ex>>,
8080
que usa uma classe e não uma clausura para implementar um decorador.
@@ -1145,6 +1145,7 @@ e a sequência inteira é apresentada como uma lista HTML.
11451145
<6> Mostra `Fraction` como uma fração.
11461146
<7> Mostra `float` e `Decimal` com a fração equivalente aproximada.
11471147

1148+
[[single_dispatch_sec]]
11481149
===== Despacho único de funções
11491150

11501151
Como não temos no Python a sobrecarga de métodos ao estilo de Java, não podemos

online/cap14.adoc

Lines changed: 91 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,17 @@ herança e criação de subclasses. Vou presumir um entendimento básico destes
2323
conceitos, que você pode ter aprendido lendo
2424
https://fpy.li/6w[O Tutorial de Python],
2525
ou trabalhando com outra linguagem orientada a objetos, tal como
26-
Java, C# ou {cpp}. Aqui vamos nos concentrar em quatro características de
26+
Java, C# ou {cpp}. Vamos nos concentrar em quatro características de
2727
Python:
2828

2929
* A função `super()`
30-
* As armadilhas na criação de subclasses de tipos embutidos
30+
* Armadilhas na criação de subclasses de tipos embutidos
3131
* Herança múltipla e a ordem de resolução de métodos
3232
* Classes mixin
3333

3434
Herança múltipla acontece quando uma classe tem mais de uma classe base.
3535
Ela existe em {cpp}, mas não em Java e C#.
36-
Muitos consideram que a herança múltipla não vale a
36+
Muitos consideram que a herança múltipla não vale
3737
os problemas que causa. Ela foi deliberadamente deixada de fora de
3838
Java, após supostamente ser usada em excesso nos primeiras bases de código em {cpp}.
3939

@@ -44,7 +44,7 @@ quando necessário.
4444
Em 2021, quando escrevo essas linhas, há uma forte reação contra o uso excessivo
4545
de herança em geral—não apenas herança múltipla—porque superclasses e subclasses
4646
são fortemente acopladas, ou seja, interdependentes. Esse acoplamento forte
47-
significa que modificações em uma classe pode ter efeitos inesperados e de longo
47+
significa que modificações em uma classe podem ter efeitos inesperados e de longo
4848
alcance em suas subclasses, tornando os sistemas frágeis e difíceis de entender.
4949

5050
Entretanto, ainda temos que dar manutenção a sistemas existentes, que podem ter
@@ -182,7 +182,7 @@ Os parâmetros são:
182182
O objeto (para chamadas a métodos de instância) ou classe (para chamadas a
183183
métodos de classe) que será o receptor da chamada ao
184184
método.footnote:[Adotamos o termo "receptor" como tradução para _receiver_,
185-
que é o objeto `o` vinculado um método `m` no momento da chamada `o.m()`.]
185+
que é o objeto `x` vinculado um método `m` no momento da chamada `x.m()`.]
186186
Por default, é `self` se a chamada `super()` acontece no corpo de um método
187187
de instância.
188188

@@ -407,7 +407,9 @@ linguagem que implemente herança múltipla precisa lidar com o
407407
potencial conflito de nomes, quando superclasses contêm métodos com nomes
408408
iguais. Este é o chamado "problema do losango" (_diamond problem_),
409409
ilustrado na <<diamond_uml>> e no <<ex_diamond>>, onde da hiearquia
410-
começa na classe base `Root` (raiz) e termina na classe `Leaf` (folha).
410+
começa na classe base `Root` (raiz) e termina na classe `Leaf`
411+
(folha).footnote:[Adotamos a convenção dos computólogos
412+
e desenhamos árvores de cabeça para baixo: a raiz no topo, as folhas na base.]
411413

412414
[[diamond_uml]]
413415
.Esquerda: Sequência de ativação para a chamada `leaf1.ping()`. Direita: Sequência de ativação para a chamada `leaf1.pong()`.
@@ -1161,7 +1163,7 @@ class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
11611163

11621164
O corpo de `ListView` é vaziofootnote:[NT: a doctring diz "Renderiza alguma
11631165
lista de objetos, definida por `self.model` ou `self.queryset`. `self.queryset`
1164-
na verdade pode ser qualquer iterável de itens, não apenas um queryset."], mas a
1166+
na pode ser qualquer iterável de itens, não apenas um queryset."], mas a
11651167
classe fornece um serviço útil: ela une uma mixin e uma classe base que devem
11661168
ser usadas em conjunto.
11671169

@@ -1388,11 +1390,11 @@ https://fpy.li/descr101[_Unifying types and classes in Python 2.2_]
13881390
(Unificando tipos e classes em Python 2.2), de Guido van Rossum. Desde então, nada
13891391
realmente importante mudou nesses recursos. Python 2.2 foi uma proeza fantástica
13901392
de evolução da linguagem, adicionando vários novos recursos poderosos em um todo
1391-
coerente, sem quebrar a compatibilidade com versões anteriores. Os novo recursos
1393+
coerente, sem quebrar a compatibilidade com versões anteriores. Os novos recursos
13921394
eram 100% opcionais. Para usá-los, bastava programar explicitamente uma
1393-
subclasse de `object`—direta ou indiretamente—, para criar uma assim chamada
1394-
"classe no novo estilo". No Python 3, todas as classes são subclasses de
1395-
`object`.
1395+
subclasse de direta ou indirta de `object`, para criar uma assim chamada
1396+
_new-style class_ (classe no novo estilo) . No Python 3,
1397+
todas as classes são subclasses de `object`.
13961398

13971399
O _Python Cookbook_, 3ª ed., de David Beazley e Brian K. Jones (O'Reilly) inclui
13981400
várias receitas mostrando o uso de `super()` e de classes mixin. Você pode
@@ -1411,17 +1413,17 @@ Knight. A resposta de Martijn Pieters a
14111413
https://fpy.li/14-41[_How to use super() with one argument?_]
14121414
(Como usar super() com um só argumento?)
14131415
inclui uma explicação concisa e aprofundada de `super`, incluindo sua relação
1414-
com descritores, um conceito que estudaremos apenas no <<ch_descriptors>>. Essa
1415-
é a natureza de `super`. Ele é simples de usar em casos de uso básicos, mas é
1416+
com descritores, um conceito que estudaremos apenas no <<ch_descriptors>>.
1417+
Assim é `super`: simples de usar nos casos básicos, mas também
14161418
uma ferramenta poderosa e complexa, que alcança alguns dos recursos dinâmicos
14171419
mais avançados de Python, raramente encontrados em outras linguagens.
14181420

1419-
Apesar dos títulos daqueles posts, o problema não é exatamente com a função
1420-
embutida `super`—que no Python 3 não é tão feia quanto era no Python 2. A
1421-
questão real é a herança múltipla, algo inerentemente complicado e traiçoeiro.
1421+
Apesar dos títulos daqueles posts, o problema não é exatamente a função
1422+
embutida `super`—que no Python 3 ficou mais fácil de usar do que era no Python 2.
1423+
A questão real é a herança múltipla, algo inerentemente complicado e traiçoeiro.
14221424
Michele Simionato vai além da crítica, e de fato oferece uma solução em seu
14231425
https://fpy.li/14-42[_Setting Multiple Inheritance Straight_]
1424-
(Colocando a Herança Múltipla em seu Lugar):
1426+
(Colocando a herança múltipla em seu devido lugar):
14251427
ele implementa _traits_ ("traços"), uma forma explícita de mixin originada na linguagem Self.
14261428
Simionato escreveu, em seu blog, uma longa série de posts sobre herança múltipla em Python, incluindo
14271429
https://fpy.li/14-43[_The wonders of cooperative inheritance, or using super in Python 3_]
@@ -1440,7 +1442,7 @@ Grady Booch et al., e o recomendo fortemente como uma introdução geral ao
14401442
pensamento orientado a objetos, independente da linguagem de programação. É um
14411443
dos raros livros que trata da herança múltipla sem preconceitos.
14421444

1443-
Hoje, mais que nunca, é de bom tom evitar a herança, então cá estão duas
1445+
Hoje, mais que nunca, aconselha-se evitar a herança. Então cá estão duas
14441446
referências sobre como fazer isso. Brandon Rhodes escreveu
14451447
https://fpy.li/14-49[_The Composition Over Inheritance Principle_]
14461448
(O princípio da composição antes da herança), parte de seu excelente guia
@@ -1462,7 +1464,7 @@ defendem para Python.
14621464
[quote, Alan Kay, The Early History of Smalltalk ("Os Primórdios de Smalltalk")]
14631465
____
14641466
1465-
[Nós] começamos a defender a ideia de herança como uma maneira de permitir que
1467+
[...] começamos a defender a ideia de herança como uma maneira de permitir que
14661468
iniciantes pudessem construir [algo] a partir de frameworks que só poderiam ser
14671469
projetadas por especialistasfootnote:[Alan Kay, _The Early History of Smalltalk_
14681470
(Os Promórdios de Smalltalk), na SIGPLAN Not. 28, 3 (março de 1993),
@@ -1475,73 +1477,102 @@ ____
14751477
A((("inheritance and subclassing", "Soapbox discussion",
14761478
id="IASsoap14")))((("Soapbox sidebars", "multilevel class hierarchies"))) imensa
14771479
maioria dos programadores escreve aplicações, não frameworks. Mesmo aqueles que
1478-
escrevem frameworks provavelmente passam muito (ou a maior parte) de seu tempo
1480+
escrevem frameworks provavelmente passam boa parte de seu tempo
14791481
escrevendo aplicações. Quando escrevemos aplicações, normalmente não precisamos
14801482
criar hierarquias de classes. No máximo escrevemos classes que são subclasses de
14811483
ABCs ou de outras classes oferecidas pelo framework. Como desenvolvedores de
14821484
aplicações, é muito raro precisarmos escrever uma classe que funcionará como
1483-
superclasse de outra. As classes que escrevemos são, quase sempre, "classes
1484-
folha" (isto é, folhas na árvore de herança).
1485+
superclasse de outra. Quase sempre as classes que escrevemos são classes
1486+
folha: classes concretas sem subclasses.
14851487
14861488
Se, trabalhando como desenvolvedor de aplicações, você se pegar criando
1487-
hierarquias de classe de múltiplos níveis, quase certamente uma ou mais das
1488-
seguintes alternativas se aplica:
1489+
hierarquias de classe de múltiplos níveis, aposto que está vivendo uma destas
1490+
situações:
14891491
14901492
* Você está reinventando a roda. Procure um framework ou biblioteca que forneça
1491-
componentes que possam ser reutilizados em sua aplicação.
1493+
componentes você possa reutilizar em sua aplicação.
14921494
14931495
* Você está usando um framework mal projetado. Procure uma alternativa.
14941496
1495-
* Você está complicando demais o processo. Lembre-se((("KISS principle"))) do
1497+
* Você está complicando demais. Lembre-se((("KISS principle"))) do
14961498
_Princípio KISS_.
14971499
14981500
* Você ficou entediado programando aplicações e decidiu criar um novo framework.
14991501
Parabéns e boa sorte!
15001502
1501-
Também é possível que todas as alternativas acima se apliquem à sua situação:
1503+
Também é possível que todas as alternativas acima descrevam situação:
15021504
você ficou entediado e decidiu reinventar a roda, escrevendo seu próprio
15031505
framework mal projetado e excessivamente complexo, e está sendo forçado a
15041506
programar classe após classe para resolver problemas triviais. Espero que você
15051507
esteja se divertindo, ou pelo menos que esteja sendo pago para fazer isso.
15061508
15071509
**Tipos embutidos mal-comportados: bug ou _feature_?**
15081510
1509-
Os((("Soapbox sidebars", "trade-offs of built-ins"))) tipos embutidos `dict`, `list`, e `str` são blocos básicos essenciais do próprio Python, então precisam ser rápidos—qualquer problema de desempenho ali teria severos impactos em praticamente todo o resto.
1510-
É por isso que o CPython adotou atalhos que fazem com que métodos embutidos se comportem mal, ao não cooperarem com os métodos sobrescritos por subclasses.
1511-
Um caminho possível para sair desse dilema seria oferecer duas implementações para cada um desses tipos: um "interno", otimizado para uso pelo interpretador, e um externo, facilmente extensível.
1512-
1513-
Mas isso nós já temos: `UserDict`, `UserList`,
1514-
e `UserString` não são tão rápidos quanto seus equivalentes embutidos,
1515-
mas são fáceis de estender.
1516-
A abordagem pragmática tomada pelo CPython significa que também podemos usar,
1517-
em nossas próprias aplicações, as implementações altamente otimizadas mas difíceis estender.
1518-
E isso faz sentido, considerando que não é tão frequente precisarmos de um mapeamento,
1519-
uma lista ou uma string customizados, mas usamos `dict`, `list`, e `str` diariamente.
1520-
Só precisamos estar cientes dos compromissos envolvidos.
1521-
1522-
1523-
1524-
[role="soapbox-title"]
1525-
Herança através das linguagens
1526-
1527-
Alan Kay((("Soapbox sidebars", "inheritance across languages"))) criou o termo "orientado a objetos", e Smalltalk tinha apenas herança simples, apesar de existirem versões com diferentes formas de suporte a herança múltipla, incluindo os dialetos modernos de Smalltalk, Squeak e Pharo, que suportam _traits_ ("traços")—um dispositivo de linguagem que pode substituir classes mixin, mas evita alguns dos problemas da herança múltipla.
1528-
1529-
A primeira linguagem popular a implementar herança múltipla foi o {cpp}, e esse recurso foi abusado o suficiente para que o Java—criado para ser um substituto do {cpp}—fosse projetado sem suporte a herança múltipla de implementação (isto é, sem classes mixin). Quer dizer, isso até o Java 8 introduzir os métodos default, que tornam interfaces muito similares às classes abstratas usadas para definir interfaces em {cpp} e em Python.
1530-
Depois de Java, a linguagem da JVM mais usada é provavelmente o Scala, que implementa _traits_.
1511+
Os((("Soapbox sidebars", "trade-offs of built-ins"))) tipos embutidos `dict`,
1512+
`list`, e `str` são blocos básicos essenciais do próprio Python, então precisam
1513+
ser rápidos—qualquer problema de desempenho ali teria severos impactos em
1514+
praticamente todo o resto. É por isso que o CPython adotou atalhos que fazem com
1515+
que muitos métodos embutidos escritos em C se comportem mal, ao não cooperarem
1516+
com os métodos sobrescritos por subclasses em Python.
1517+
1518+
Uma solução para este dilema seria oferecer duas implementações para cada um
1519+
desses tipos: uma "interno", otimizada para uso pelo interpretador, e uma externa,
1520+
facilmente extensível.
1521+
1522+
Mas veja só, isso nós já temos: `UserDict`, `UserList`, e `UserString` não são
1523+
tão rápidos quanto seus equivalentes embutidos, mas são fáceis de estender. A
1524+
abordagem pragmática tomada pelo CPython significa que também podemos usar, em
1525+
nossas próprias aplicações, as implementações altamente otimizadas mas difíceis
1526+
estender. E isso faz sentido, considerando que não é tão frequente precisarmos
1527+
de um mapeamento, uma lista ou uma string customizados, mas usamos `dict`,
1528+
`list`, e `str` diariamente. Só precisamos estar cientes dos compromissos
1529+
envolvidos.
1530+
1531+
1532+
**Herança através das linguagens**
1533+
1534+
Alan Kay((("Soapbox sidebars", "inheritance across languages"))) criou o termo
1535+
"orientado a objetos", e Smalltalk tinha apenas herança simples, apesar de
1536+
existirem versões com diferentes formas de suporte a herança múltipla, incluindo
1537+
os dialetos modernos de Smalltalk, Squeak e Pharo, que suportam _traits_
1538+
("traços")—um dispositivo de linguagem que pode substituir classes mixin, mas
1539+
evita alguns dos problemas da herança múltipla.
1540+
1541+
A primeira linguagem popular a implementar herança múltipla foi o {cpp}, e esse
1542+
recurso foi abusado o suficiente para que o Java—criado para ser um substituto
1543+
do {cpp}—fosse projetado sem suporte a herança múltipla de implementação (isto
1544+
é, sem classes mixin). Quer dizer, isso até o Java 8 (e Kotlin) permitir métodos
1545+
default, que que aproximam suas interfaces do conceito de classes abstratas
1546+
que temps em Python e {cpp}.
15311547
15321548
Outras linguagens que suportam _traits_ são versões recentes de PHP e Groovy,
1533-
bem como Rust e Raku—a linguagem antes conhecida como Perl 6.footnote:[Meu amigo e revisor técnico Leonardo Rochael explica isso melhor do que eu poderia:
1534-
"A existência continuada junto com o persistente adiamento da chegada do Perl 6 estava drenando a força de vontade da evolução do próprio Perl. Agora o Perl continua a ser desenvolvido como uma linguagem separada (está na versão 5.34), sem a ameaça de ser descontinuada pela linguagem antes conhecida como Perl 6."]
1549+
bem como Rus, Scala, t e Raku—a linguagem antes conhecida como Perl 6.footnote:[Meu amigo
1550+
e revisor técnico Leonardo Rochael explica isso melhor do que eu poderia: "A
1551+
existência continuada junto com o persistente adiamento da chegada do Perl 6
1552+
estava drenando a força de vontade da evolução do próprio Perl. Agora o Perl
1553+
continua a ser desenvolvido como uma linguagem separada (está na versão 5.34),
1554+
sem a ameaça de ser descontinuada pela linguagem antes conhecida como Perl 6."]
15351555
Então podemos dizer que _traits_ estão na moda em 2021.
15361556
1537-
Ruby traz uma perspectiva original para a herança múltipla:
1538-
não a suporta, mas introduz mixins como um recurso explícito da linguagem. Uma classe Ruby pode incluir um módulo em seu corpo, e aí os métodos definidos no módulo se tornam parte da implementação da classe.
1539-
Essa é uma forma "pura" de mixin, sem herança envolvida, e está claro que uma mixin Ruby não tem qualquer influência sobre o tipo da classe onde ela é usada.
1540-
Isso oferece os benefícios das mixins, evitando muitos de seus problemas mais comuns.
1541-
1542-
Duas novas linguagens orientadas a objetos que estão recebendo muita atenção limitam severamente a herança: Go e Julia.
1543-
Ambas giram em torno de programar "objetos" implementando "métodos", e suportam https://fpy.li/7b[polimorfismo], mas evitam o termo "classe".
1544-
1545-
Go não tem qualquer tipo de herança, mas oferece uma sintaxe que facilita a composição. Julia tem uma hierarquia de tipos, mas subtipos não podem herdar estrutura, apenas comportamentos, e só é permitido criar subtipos de tipos abstratos. Além disso, os métodos de Julia são implementados com despacho múltiplo—uma forma mais avançada do mecanismo que vimos na <<generic_functions_sec>>.((("", startref="IASsoap14")))
1557+
Ruby traz uma perspectiva original para a herança múltipla: não a suporta, mas
1558+
introduz mixins como um recurso explícito da linguagem. Uma classe Ruby pode
1559+
incluir um módulo em seu corpo, e aí os métodos definidos no módulo se tornam
1560+
parte da implementação da classe. Essa é uma forma "pura" de mixin, sem herança
1561+
envolvida, e está claro que uma mixin Ruby não tem qualquer influência sobre o
1562+
tipo da classe onde ela é usada. Isso oferece os benefícios das mixins, evitando
1563+
muitos de seus problemas mais comuns.
1564+
1565+
Duas novas linguagens orientadas a objetos que estão recebendo muita atenção
1566+
limitam severamente a herança: Go e Julia. Ambas giram em torno de programar
1567+
"objetos" implementando "métodos", e suportam https://fpy.li/7b[polimorfismo],
1568+
mas evitam o termo "classe".
1569+
1570+
Go não tem qualquer tipo de herança, mas oferece uma sintaxe que facilita a
1571+
composição de suas interfaces e structs. Julia tem uma hierarquia de tipos, mas
1572+
subtipos não podem herdar estrutura, só comportamentos, e só é permitido
1573+
criar subtipos de tipos abstratos. Além disso, os métodos de Julia são
1574+
implementados com despacho múltiplo—uma forma mais avançada do mecanismo de
1575+
despacho único que vimos na <<single_dispatch_sec>>.((("",
1576+
startref="IASsoap14")))
15461577
15471578
****

0 commit comments

Comments
 (0)