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
Conjuntos((("sets", "set theory", id=Stheory03")))((("dictionaries and sets", "set theory", id="DASset03"))) não são novidade no Python, mais ainda são um tanto subutilizados. O tipo `set` e seu irmão imutável, `frozenset`, surgiram inicialmente como módulos, na biblioteca padrão do Python 2.3, e foram promovidos a tipos embutidos no Python 2.6.
890
+
Conjuntos((("sets", "set theory", id=Stheory03")))((("dictionaries and sets", "set theory", id="DASset03")))((("frozenset")))
891
+
não são novidade no Python, mais ainda são um tanto subutilizados.
892
+
O tipo `set` e seu irmão imutável, `frozenset`,
893
+
surgiram inicialmente como módulos na biblioteca padrão do Python 2.3,
894
+
e foram promovidos a tipos embutidos no Python 2.6.
891
895
892
896
[NOTE]
893
897
====
894
-
Nesse((("frozenset"))) livro, uso a palavra "conjunto" para me referir tanto a `set` quanto a `frozenset`. Quando falo especificamente sobre a classe `set`, uso a fonte de espaçamento constante: `set`.
898
+
Nesse livro, uso a palavra "conjunto" para me referir tanto a `set` quanto a `frozenset`.
895
899
====
896
900
897
-
Um conjunto é uma coleção de objetos únicos. Um caso de uso básico é a remoção de itens duplicados:
901
+
Um conjunto é uma coleção de objetos únicos. Uma grande utilidade dos conjuntos é descartar itens duplicados:
Elementos de um conjunto devem ser hashable. O tipo `set` não é hashable, então não é possível criar um `set` com instâncias aninhadas de `set`. Mas `frozenset` é hashable, então você pode ter elementos `frozenset` dentro de um `set`.
924
+
Elementos de um conjunto devem ser _hashable_.
925
+
O tipo `set` não é hashable, então não é possível criar um `set` com instâncias aninhadas de `set`.
926
+
Mas `frozenset` é hashable, então você pode ter instâncias de `frozenset` dentro de um `set`.
921
927
922
-
Além de impor a unicidade de cada elemento, os tipos conjunto implementam muitas operações entre conjuntos como operadores infixos. Assim, dados dois conjuntos `a` e `b`, `a | b` devolve sua união, `a & b` calcula a intersecção, `a - b` a diferença, e `a ^ b` a diferença simétrica. Usadas com sabedoria, as operações de conjuntos podem reduzir tanto a contagem de linhas quanto o tempo de execução de programas Python, ao mesmo tempo em que tornam o código mais legível e mais fácil de entender e debater—pela remoção de loops e da lógica condicional.
928
+
Além de impor a unicidade de cada elemento,
929
+
os tipos conjunto implementam muitas operações entre conjuntos como operadores infixos.
930
+
Assim, dados dois conjuntos `a` e `b`, `a | b` devolve sua união,
931
+
`a & b` calcula a intersecção, `a - b` a diferença, e `a ^ b` a diferença simétrica.
932
+
Quando bem utilizadas,
933
+
as operações de conjuntos podem reduzir tanto a contagem de linhas quanto o tempo de execução de programas Python,
934
+
ao mesmo tempo em que tornam o código mais legível e mais fácil de entender—pela remoção de loops e lógica condicional.
923
935
924
-
Por exemplo, imagine que você tem um grande conjunto de endereços de email (o `palheiro`—_haystack_) e um conjunto menor de endereços (as `agulhas`—_needles_), e precisa contar quantas `agulhas` existem no `palheiro`. Graças à interseção de `set` (o operador `&`), é possível programar isso em uma única linha (veja o <<ex_set_ops_ex>>).
936
+
Por exemplo, imagine que você tem um grande conjunto de endereços de email (o "palheiro"—`haystack`)
937
+
e um conjunto menor de endereços (as "agulhas"—`needles``),
938
+
e precisa contar quantas agulhas existem no palheiro.
939
+
Graças à interseção de `set` (o operador `&`),
940
+
é possível codar isso em uma expressão simples (veja o <<ex_set_ops_ex>>).
925
941
926
942
[[ex_set_ops_ex]]
927
943
.Conta as ocorrências de agulhas (_needles_) em um palheiro (_haystack_), ambos do tipo set
@@ -946,7 +962,10 @@ for n in needles:
946
962
----
947
963
====
948
964
949
-
O <<ex_set_ops_ex>> é um pouco mais rápido que o <<ex_set_loop_ex>>. Por outros lado, o <<ex_set_loop_ex>> funciona para quaisquer objetos iteráveis `needles` e `haystack`, enquanto o <<ex_set_ops_ex>> exige que ambos sejam conjuntos. Mas se você não tem conjuntos à mão, pode sempre criá-los na hora, como mostra o <<ex_set_ops_ex2>>.
965
+
O <<ex_set_ops_ex>> é um pouco mais rápido que o <<ex_set_loop_ex>>.
966
+
Por outro lado, o <<ex_set_loop_ex>> funciona para quaisquer objetos iteráveis `needles` e `haystack`,
967
+
enquanto o <<ex_set_ops_ex>> exige que ambos sejam conjuntos.
968
+
Mas se você não tem conjuntos à mão, pode sempre criá-los na hora, como mostra o <<ex_set_ops_ex2>>.
950
969
951
970
[[ex_set_ops_ex2]]
952
971
.Conta as ocorrências de agulhas (_needles_) em um palheiro (_haystack_); essas linhas funcionam para qualquer tipo iterável
@@ -960,24 +979,34 @@ found = len(set(needles).intersection(haystack))
960
979
----
961
980
====
962
981
963
-
Claro, há o custo extra envolvido na criação dos conjuntos no <<ex_set_ops_ex2>>, mas se ou as `needles` ou o `haystack` já forem um `set`, a alternativa no <<ex_set_ops_ex2>> pode ser mais barata que o <<ex_set_loop_ex>>.
982
+
Claro, há o custo extra envolvido na criação dos conjuntos no <<ex_set_ops_ex2>>,
983
+
mas se ou as `needles` ou o `haystack` já forem um `set`,
984
+
a alternativa no <<ex_set_ops_ex2>> pode ser mais barata que o <<ex_set_loop_ex>>.
964
985
965
-
Qualquer dos exemplos acima é capaz de buscar 1000 elementos em um `haystack` de 10,000,000 de itens em cerca de 0,3 milisegundos—isso é próximo de 0,3 microsegundos por elemento.
986
+
Qualquer dos exemplos acima é capaz de buscar 1000 elementos em um `haystack` de 10 milhões
987
+
de itens em cerca de 0,3 milisegundos—isso é cerca de 0,3 microsegundos por elemento.
966
988
967
-
Além do teste de existência extremamente rápido (graças à tabela de hash subjacente), os tipos embutidos `set` e `frozenset` oferecem uma rica API para criar novos conjuntos ou, no caso de `set`, para modificar conjuntos existentes. Vamos discutir essas operações em breve, após uma observação sobre sintaxe.((("", startref="Stheory03")))
989
+
Além do teste de existência extremamente rápido (graças à tabela de hash subjacente),
990
+
os tipos embutidos `set` e `frozenset` oferecem uma rica API para criar novos conjuntos ou,
991
+
no caso de `set`, para modificar conjuntos existentes.
992
+
Vamos discutir essas operações em breve, após uma observação sobre sintaxe.((("", startref="Stheory03")))
968
993
969
994
970
995
==== Sets literais
971
996
972
-
A((("sets", "set literals"))) sintaxe de literais `set`—`{1}`, `{1, 2}`, etc.—parece exatamente igual à notação matemática, mas tem uma importante exceção: não há notação literal para o `set` vazio, então precisamos nos lembrar de escrever `set()`.
997
+
A((("sets", "set literals"))) sintaxe de literais `set`—`{1}`, `{1, 2}`, etc.—parece
998
+
muito com a notação matemática, mas tem uma importante exceção:
999
+
não há notação literal para o `set` vazio, então precisamos nos lembrar de escrever `set()`.
973
1000
974
1001
.Peculiaridade sintática
975
1002
[WARNING]
976
1003
====
977
-
Não esqueça que, para criar um `set` vazio, é preciso usar o construtor sem argumentos: `set()`. Se você escrever `{}`, vai criar um +dict+ vazio—isso não mudou no Python 3.
1004
+
Para criar um `set` vazio, usamos o construtor sem argumentos: `set()`.
1005
+
Se você escrever `{}`, vai criar um +dict+ vazio—isso não mudou no Python 3.
978
1006
====
979
1007
980
-
No Python 3, a representação padrão dos sets como strings sempre usa a notação `{…}`, exceto para o conjunto vazio:
1008
+
No Python 3, a representação padrão dos sets como strings sempre usa a notação `{…}`,
1009
+
exceto para o conjunto vazio:
981
1010
982
1011
[source, pycon]
983
1012
----
@@ -992,10 +1021,15 @@ No Python 3, a representação padrão dos sets como strings sempre usa a notaç
992
1021
set()
993
1022
----
994
1023
995
-
[role="pagebreak-before less_space"]
996
-
A sintaxe do `set` literal, como `{1, 2, 3}`, é mais rápida e mais legível que uma chamada ao construtor (por exemplo, `set([1, 2, 3])`). Essa última forma é mais lenta porque, para avaliá-la, o Python precisa buscar o nome `set` para obter seu construtor, daí criar uma lista e, finalmente, passá-la para o construtor. Por outro lado, para processar um literal como `{1, 2, 3}`, o Python roda um bytecode especializado, `BUILD_SET`.footnote:[Isso pode ser interessante, mas não é super importante. Essa diferença de velocidade vai ocorrer apenas quando um conjunto literal for avaliado, e isso acontece no máximo uma vez por processo Python—quando um módulo é compilado pela primeira vez. Se você estiver curiosa, importe a função `dis` do módulo `dis`, e a use para desmontar os bytecodes para um `set` literal—por exemplo, `dis('{1}')`—e uma chamada a `set`—`+dis('set([1])')+`]
1024
+
A sintaxe do `set` literal, como `{1, 2, 3}`, é mais rápida e mais legível que uma chamada ao construtor (por exemplo, `set([1, 2, 3])`).
1025
+
Essa última forma é mais lenta porque, para avaliá-la, o Python precisa buscar o nome `set` para obter seu construtor,
1026
+
daí criar uma lista e, finalmente, passá-la para o construtor.
1027
+
Por outro lado, para processar um literal como `{1, 2, 3}`,
1028
+
o Python roda um bytecode especializado, `BUILD_SET`.footnote:[Isso pode ser interessante, mas não é super importante. Essa diferença de velocidade vai ocorrer apenas quando um conjunto literal for avaliado, e isso acontece no máximo uma vez por processo Python—quando um módulo é compilado pela primeira vez. Se você estiver curiosa, importe a função `dis` do módulo `dis`, e a use para inspecionar os bytecodes de um `set` literal—por exemplo, `dis('{1}')`—e uma chamada ao construtor `set`—`+dis('set([1])')+`]
997
1029
998
-
Não há sintaxe especial para representar literais `frozenset`—eles devem ser criados chamando seu construtor. Sua representação padrão como string no Python 3 se parece com uma chamada ao construtor de `frozenset`. Observe a saída na sessão de console a seguir:
1030
+
Não há sintaxe especial para representar literais `frozenset`—eles só podem ser criados chamando seu construtor.
1031
+
Sua representação padrão como string no Python 3 se parece com uma chamada ao construtor de `frozenset` com um argumento `set``.
<2> `b` é salvo como uma anotação, e também se torna um atributo de classe com o valor `1.1`.
535
535
<3> `c` é só um bom e velho atributo de classe básico, sem uma anotação.
536
536
537
-
Podemos checar isso no console, primeiro lendo o `+__annotations__+` da `DemoPlainClass`, e daí tentando obter os atributos chamados `a`, `b`, e `c`:
537
+
Podemos checar isso no console, primeiro lendo o `+__annotations__+` da `DemoPlainClass`,
538
+
e daí tentando obter os atributos chamados `a`, `b`, e `c`:
538
539
539
540
[source, pycon]
540
541
----
@@ -551,17 +552,22 @@ AttributeError: type object 'DemoPlainClass' has no attribute 'a'
551
552
'spam'
552
553
----
553
554
554
-
Observe que o atributo especial `+__annotations__+` é criado pelo interpretador para registrar dicas de tipo que aparecem no código-fonte—mesmo em uma classe básica.
555
+
Observe que o atributo especial `+__annotations__+` é criado pelo interpretador
556
+
para registrar dicas de tipo que aparecem no código-fonte—mesmo em uma classe básica.
555
557
556
-
O `a` sobrevive apenas como uma anotação, não se torna um atributo da classe, porque nenhum valor é atribuído a ele.footnote:[O conceito de _undefined_, um dos erros mais idiotas no design do Javascript, não existe no Python. Obrigado, Guido!]
558
+
O `a` sobrevive apenas como uma anotação, não se torna um atributo da classe, porque nenhum valor é atribuído a
559
+
ele.footnote:[O conceito de _undefined_, um dos erros mais tolos no design do Javascript, não existe no Python. Obrigado, Guido!]
557
560
O `b` e o `c` são armazenados como atributos de classe porque são vinculados a valores.
558
561
559
562
Nenhum desses três atributos estará em uma nova instância de `DemoPlainClass`.
560
-
Se você criar um objeto `o = DemoPlainClass()`, `o.a` vai gerar um `AttributeError`, enquanto `o.b` e `o.c` vão obter os atributos de classe com os valores `1.1` e `'spam'`—que é apenas o comportamento normal de um objeto Python.
563
+
Se você criar um objeto `o = DemoPlainClass()`, `o.a` vai gerar um `AttributeError`,
564
+
enquanto `o.b` e `o.c` vão obter os atributos de classe com os valores
565
+
`1.1` e `'spam'`—que é apenas o comportamento normal de um objeto Python.
561
566
562
567
===== Inspecionando uma typing.NamedTuple
563
568
564
-
Agora vamos examinar uma classe criada com `typing.NamedTuple` (<<ex_demo_nt>>), usando os mesmos atributos e anotações da `DemoPlainClass` do <<ex_demo_plain>>.
569
+
Agora vamos examinar uma classe criada com `typing.NamedTuple` (<<ex_demo_nt>>),
570
+
usando os mesmos atributos e anotações da `DemoPlainClass` do <<ex_demo_plain>>.
565
571
566
572
[[ex_demo_nt]]
567
573
.meaning/demo_nt.py: uma classe criada com `typing.NamedTuple`
0 commit comments