sábado, 8 de maio de 2021

Tipos de dados nativos em Python

❝A admiração é o fundamento de toda filosofia, a investigação de seu progresso, a ignorância seu fim.❞
- Michel de Montaigne

Mergulho

Tipos de dados. Deixe de lado seu primeiro programa Python por apenas um minuto e vamos falar sobre tipos de dados. Em Python, todo valor tem um tipo de dados, mas você não precisa declarar o tipo de dados das variáveis. Como isso funciona? Com base na atribuição original de cada variável, o Python descobre que tipo é e mantém o controle disso internamente.

Python tem muitos tipos de dados nativos. Aqui estão os mais importantes:

  1. Os booleanos são True ou False.
  2. Os números podem ser inteiros (1 e 2), flutuantes (1.1 e 1.2), frações (1/2 e 2/3) ou até mesmo números complexos.
  3. Strings são sequências de caracteres Unicode, por exemplo, um documento HTML.
  4. Bytes e matrizes de bytes, por exemplo, um arquivo de imagem JPEG.
  5. As listas são sequências ordenadas de valores.
  6. As tuplas são sequências ordenadas e imutáveis de valores.
  7. Conjuntos (sets) são pacotes não ordenados de valores.
  8. Os dicionários são pacotes não ordenados de pares de chave-valores.

Claro, existem mais tipos do que estes. Tudo é um objeto em Python, portanto, existem tipos como módulo, função, classe , método, arquivo e até mesmo código compilado. Você já viu alguns destes: módulos têm nomes, funções têm docstrings. Você aprenderá sobre classes em Classes & Iterators e sobre arquivos em Files.

Strings e bytes são importantes o suficiente - e complicados o suficiente - para que tenham seu próprio capítulo. Vamos examinar os outros primeiro.

Boolean

Você pode usar virtualmente qualquer expressão em um contexto booleano.

Os booleanos são verdadeiros ou falsos. Python tem duas constantes, habilmente nomeadas True e False, que podem ser usadas para atribuir valores booleanos diretamente. As expressões também podem ser avaliadas como um valor booleano. Em certos lugares (como instruções if), Python espera que uma expressão seja avaliada como um valor booleano. Esses locais são chamados de contextos booleanos. Você pode usar virtualmente qualquer expressão em um contexto booleano, e o Python tentará determinar seu valor verdadeiro. Tipos de dados diferentes têm regras diferentes sobre quais valores são verdadeiros ou falsos em um contexto booleano. (Isso fará mais sentido quando você ver alguns exemplos concretos posteriormente neste capítulo.)

Por exemplo, pegue este snippet de teste.py:

if tamanho < 0:
    raise ValueError('O número não deve ser negativo')

tamanho é um número inteiro, 0 é um número inteiro e < é um operador numérico. O resultado da expressão tamanho < 0 é sempre um booleano. Você mesmo pode testar isso no shell interativo do Python:

>>> tamanho = 1
>>> tamanho < 0
False
>>> tamanho = 0
>>> tamanho < 0
False
>>> tamanho = -1
>>> tamanho < 0
True

Devido a alguns problemas herdados que sobraram do Python 2, os booleanos podem ser tratados como números. True é 1; False é 0.

>>> True + True
2
>>> True - False
1
>>> True * False
0
>>> True / False
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero

Eca, Eca, Eca! Não faça isso. Esqueça que eu mencionei isso.

Números

Os números são fantásticos. Existem tantos para escolher Python suporta tanto números inteiros quanto números de ponto flutuante. Não há declaração de tipo para distingui-los; Python os diferencia pela presença ou ausência de um ponto decimal.

>>> type(1)                 ①
<class 'int'>
>>> isinstance(1, int)      ②
True
>>> 1 + 1                   ③
2
>>> 1 + 1.0                 ④
2.0
>>> type(2.0)
<class 'float'>
  1. Você pode usar a função type() para verificar o tipo de qualquer valor ou variável. Como você pode esperar, 1 é um int.
  2. Da mesma forma, você pode usar a função isinstance() para verificar se um valor ou variável é de um determinado tipo.
  3. Adicionar um int a um int resulta em um int.
  4. Adicionando um int a um float resulta um float. Python força o int num float para realizar a adição e retorna um float como resultado.

Coagindo inteiros para floats e vice-versa

Como você acabou de ver, alguns operadores (como adição) forçarão os inteiros a números de ponto flutuante conforme necessário. Você também pode coagi-los por si mesmo.

>>> float(2)                ①
2.0
>>> int(2.0)                ②
2
>>> int(2.5)                ③
2
>>> int(-2.5)               ④
-2
>>> 1.12345678901234567890  ⑤
1.1234567890123457
>>> type(1000000000000000)  ⑥
<class 'int'>
  1. Você pode coagir explicitamente um int para um float chamando a função float().
  2. Sem surpresa, você também pode coagir a float para um int chamando a função int().
  3. A função int() irá truncar, não arredondar.
  4. A função int() trunca números negativos em direção a 0. É uma verdadeira função de truncar, não uma função de piso.
  5. Os números de vírgula flutuante têm precisão de 15 casas decimais.
  6. Os inteiros podem ser arbitrariamente grandes.

Observação

Python 2 tinha tipos separados para int e long. O tipo de dados int era limitado por sys.maxint, que variava de acordo com a plataforma, mas geralmente era 232-1. O Python 3 tem apenas um tipo inteiro, que se comporta principalmente como o tipo antigo long do Python 2. Consulte PEP 237 para obter detalhes.

Operações Numéricas Comuns

Você pode fazer todo tipo de coisa com números.

>>> 11 / 2      ①
5.5
>>> 11 // 2     ②
5
>>> −11 // 2    ③
−6
>>> 11.0 // 2   ④
5.0
>>> 11 ** 2     ⑤
121
>>> 11 % 2      ⑥
1
  1. O operador / realiza a divisão de ponto flutuante. Ele retorna um float mesmo se o numerador e o denominador forem ints.
  2. O operador // realiza um tipo peculiar de divisão inteira. Quando o resultado for positivo, você pode pensar nisso como um truncamento (não um arredondamento) para 0 casas decimais, mas tenha cuidado com isso.
  3. Ao dividir números negativos inteiros, o operador // arredonda “para cima” para o inteiro mais próximo. Matematicamente falando, está arredondando “para baixo”, uma vez que −6 é menor que −5, mas pode truncá-lo se você estiver esperando que trunque para −5.
  4. O operador // nem sempre retorna um número inteiro. Se o numerador ou denominador for um float, ele ainda será arredondado para o inteiro mais próximo, mas o valor de retorno real será um float.
  5. O operador ** significa "elevado à potência de." 112 é 121.
  6. O operador % dá o resto após realizar a divisão inteira. 11 dividido por 2 é 5 com um resto de 1, então o resultado aqui é 1.

Observação

No Python 2, o operador / geralmente significa divisão inteira, mas você pode fazer com que ele se comporte como uma divisão de ponto flutuante incluindo uma diretiva especial em seu código. No Python 3, o operador / sempre significa divisão de ponto flutuante. Veja PEP 238 para detalhes.

Frações

Python não se limita a números inteiros e números de ponto flutuante. Ele também pode fazer toda a matemática sofisticada que você aprendeu no colégio e rapidamente se esqueceu dela.

>>> import fractions              ①
>>> x = fractions.Fraction(1, 3)  ②
>>> x
Fraction(1, 3)
>>> x * 2                         ③
Fraction(2, 3)
>>> fractions.Fraction(6, 4)      ④
Fraction(3, 2)
>>> fractions.Fraction(0, 0)      ⑤
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "fractions.py", line 96, in __new__
    raise ZeroDivisionError('Fraction(%s, 0)' % numerator)
ZeroDivisionError: Fraction(0, 0)
  1. Para começar a usar frações, importe o módulo fractions.
  2. Para definir uma fração, crie um objeto Fraction e passe o numerador e o denominador.
  3. Você pode realizar todas as operações matemáticas usuais com frações. As operações retornam um novo objeto Fraction. 2 * (1/3) = (2/3)
  4. O objeto Fraction irá reduzir automaticamente as frações. (6/4) = (3/2)
  5. Python tem o bom senso de não criar uma fração com denominador zero.

Trigonometria

Você também pode fazer trigonometria básica em Python.

>>> import math
>>> math.pi                ①
3.1415926535897931
>>> math.sin(math.pi / 2)  ②
1.0
>>> math.tan(math.pi / 4)  ③
0.99999999999999989
  1. O módulo math tem uma constante para π, a razão entre a circunferência de um círculo e seu diâmetro.
  2. O módulo math possui todas as funções trigonométricas básicas, incluindo sin(), cos(), tan(), e variantes como asin().
  3. Observe, no entanto, que Python não tem precisão infinita. tan(π / 4) deve retornar 1.0, não 0.99999999999999989.

Números em um contexto booleano

Os valores zero são falsos e os valores diferentes de zero são verdadeiros.

Você pode usar números em um contexto booleano, como uma instrução if. Os valores zero são falsos e os valores diferentes de zero são verdadeiros.

>>> def eh_verdadeiro(qualquer_coisa):       ①
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro(1)                         ②
sim, é verdadeiro
>>> eh_verdadeiro(-1)
sim, é verdadeiro
>>> eh_verdadeiro(0)
não, é verdadeiro
>>> eh_verdadeiro(0.1)                       ③
sim, é verdadeiro
>>> eh_verdadeiro(0.0)
não, é verdadeiro
>>> import fractions
>>> eh_verdadeiro(fractions.Fraction(1, 2))  ④
sim, é verdadeiro
>>> eh_verdadeiro(fractions.Fraction(0, 1))
não, é verdadeiro
  1. Você sabia que pode definir suas próprias funções no shell interativo do Python? Basta pressionar ENTER no final de cada linha e ENTER em uma linha em branco para finalizar.
  2. Em um contexto booleano, inteiros diferentes de zero são verdadeiros; 0 é falso.
  3. Números de ponto flutuante diferentes de zero são verdadeiros; 0.0 é falso. Tenha cuidado com este! Se houver o menor erro de arredondamento (não impossível, como você viu na seção anterior), o Python estará testando 0.0000000000001 em vez de 0 e retornará True.
  4. As frações também podem ser usadas em um contexto booleano. Fraction(0, n) é falso para todos os valores de n. Todas as outras frações são verdadeiras.

Listas

Listas são o tipo de dados mais poderoso do Python. Quando eu digo “ lista ”, você pode estar pensando “array cujo tamanho que tem que declarar de antemão, que só pode conter itens do mesmo tipo, e c.” Não pense assim. Listas são muito mais legais do que isso.

Observação

Uma lista em Python é como um array em Perl 5. No Perl 5, as variáveis que armazenam arrays sempre começam com o caractere @; no Python, as variáveis podem ter qualquer nome, e o Python rastreia o tipo de dados internamente.

Observação

Uma lista em Python é muito mais do que um array em Java (embora possa ser usada como um se isso for realmente tudo o que você deseja da vida). Uma analogia melhor seria com a classe ArrayList, que pode conter objetos arbitrários e pode se expandir dinamicamente à medida que novos itens são adicionados.

Criando uma lista

Criar uma lista é fácil: use colchetes para envolver uma lista de valores separados por vírgulas.

>>> uma_lista = ['a', 'b', 'mpilgrim', 'z', 'example']  ①
    >>> uma_lista
['a', 'b', 'mpilgrim', 'z', 'example']
>>> uma_lista[0]                                        ②
'a'
>>> uma_lista[4]                                        ③
'example'
>>> uma_lista[-1]                                       ④
'example'
>>> uma_lista[-3]                                       ⑤
'mpilgrim'
  1. Primeiro, você define uma lista de cinco itens. Observe que eles mantêm sua ordem original. Isso não é um acidente. Uma lista é um set ordenado de itens.
  2. Uma lista pode ser usada como uma matriz baseada em zero. O primeiro item de qualquer lista não vazia é sempre uma_lista[0].
  3. O último item desta lista de cinco itens é uma_lista[4] porque as listas são sempre baseadas em zero.
  4. Um índice negativo acessa itens do final da lista em contagem regressiva. O último item de qualquer lista não vazia é sempre uma_lista[-1].
  5. Se o índice negativo é confuso para você, pense nisso desta maneira: uma_lista[-n] == uma_lista[len(uma_lista) - n]. Portanto, nesta lista, uma_lista[-3] == uma_lista[5 - 3] == uma_lista[2].

Slicing uma lista

uma_lista[0] é o primeiro item de uma_lista.

Depois de definir uma lista, você pode obter qualquer parte dela como uma nova lista. Isso é chamado de fatiar (slicing) a lista.

>>> uma_lista
['a', 'b', 'mpilgrim', 'z', 'example']
>>> uma_lista[1:3]            ①
['b', 'mpilgrim']
>>> uma_lista[1:-1]           ②
['b', 'mpilgrim', 'z']
>>> uma_lista[0:3]            ③
['a', 'b', 'mpilgrim']
>>> uma_lista[:3]             ④
['a', 'b', 'mpilgrim']
>>> uma_lista[3:]             ⑤
['z', 'example']
>>> uma_lista[:]              ⑥
['a', 'b', 'mpilgrim', 'z', 'example']
  1. Você pode obter uma parte de uma lista, chamada de “slicing”, especificando dois índices. O valor de retorno é uma nova lista contendo todos os itens da lista, em ordem, começando com o índice da primeira fatia (neste caso uma_lista[1]), até mas não incluindo o índice da segunda fatia (neste caso uma_lista[3]).
  2. O fatiamento funciona se um ou ambos os índices de fatia forem negativos. Se ajudar, você pode pensar da seguinte maneira: lendo a lista da esquerda para a direita, o índice da primeira fatia especifica o primeiro item que você deseja e o índice da segunda fatia especifica o primeiro item que você não deseja. O valor de retorno é tudo o que está entre os dois.
  3. As listas são baseadas em zero, portanto, uma_lista[0:3] retorna os três primeiros itens da lista, começando em uma_lista[0], até, mas não incluindo uma_lista[3].
  4. Se o índice da fatia esquerda for 0, você pode deixá-lo de fora e 0 está implícito. Então uma_lista[:3] é o mesmo que uma_lista[0:3], porque o 0 inicial está implícito.
  5. Da mesma forma, se o índice de fatia correto for o comprimento da lista, você pode deixá-lo de fora. Então uma_lista[3:] é o mesmo que uma_lista[3:5], porque essa lista tem cinco itens. Há uma simetria agradável aqui. Nesta lista de cinco itens, uma_lista[:3] retorna os 3 primeiros itens e uma_lista[3:] retorna os dois últimos itens. Na verdade, uma_lista[:n] sempre retornará os primeiros n itens e uma_lista[n:] retornará os demais, independentemente do comprimento da lista.
  6. Se ambos os índices de fatias forem omitidos, todos os itens da lista serão incluídos. Mas isso não é o mesmo que a variável uma_lista original. É uma nova lista que contém todos os mesmos itens. uma_lista[:] é uma abreviatura para fazer uma cópia completa de uma lista.

Adicionando itens a uma lista

Existem quatro maneiras de adicionar itens a uma lista.

>>> uma_lista = ['a']
>>> uma_lista = uma_lista + [2.0, 3] ①
>>> uma_lista                        ②
['a', 2.0, 3]
>>> uma_lista.append(True)           ③
>>> uma_lista
['a', 2.0, 3, True]
>>> uma_lista.extend(['four', 'Ω'])  ④
>>> uma_lista
['a', 2.0, 3, True, 'four', 'Ω']
>>> uma_lista.insert(0, 'Ω')         ⑤
>>> uma_lista
['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
  1. O operador + concatena listas para criar uma nova lista. Uma lista pode conter qualquer número de itens; não há limite de tamanho (além da memória disponível). No entanto, se a memória for uma preocupação, você deve estar ciente de que a concatenação de lista cria uma segunda lista na memória. Nesse caso, essa nova lista é imediatamente atribuída à variável uma_lista existente. Portanto, essa linha de código é realmente um processo de duas etapas - concatenação e atribuição - que pode (temporariamente) consumir muita memória quando você está lidando com listas grandes.
  2. Uma lista pode conter itens de qualquer tipo de dados, e os itens em uma única lista não precisam ser todos do mesmo tipo. Aqui temos uma lista contendo uma string, um número de ponto flutuante e um inteiro.
  3. O método append() adiciona um único item ao final da lista. (Agora temos quatro tipos de dados diferentes na lista!).
  4. As listas são implementadas como classes. “Criar” uma lista é, na verdade, instanciar uma classe. Como tal, uma lista possui métodos que operam nela. O método extend() pega um argumento, uma lista, e acrescenta cada um dos itens do argumento à lista original.
  5. O método insert() insere um único item em uma lista. O primeiro argumento é o índice do primeiro item da lista que sairá da posição. Os itens da lista não precisam ser exclusivos; por exemplo, agora existem dois itens separados com o valor 'Ω': o primeiro item uma_lista[0], e o último item uma_lista[6].

Observação

uma_lista.insert(0, value) é como a função unshift() em Perl. Ele adiciona um item ao início da lista e todos os outros itens têm seu índice posicional aumentado para abrir espaço.

Vamos examinar mais de perto a diferença entre append() e extend().

>>> uma_lista = ['a', 'b', 'c']
>>> uma_lista.extend(['d', 'e', 'f'])  ①
>>> uma_lista
['a', 'b', 'c', 'd', 'e', 'f']
>>> len(uma_lista)                     ②
6
>>> uma_lista[-1]
'f'
>>> uma_lista.append(['g', 'h', 'i'])  ③
>>> uma_lista
['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']]
>>> len(uma_lista)                     ④
7
>>> uma_lista[-1]
['g', 'h', 'i']
  1. O método extend() recebe um único argumento, que é sempre uma lista, e adiciona cada um dos itens dessa lista a uma_lista.
  2. Se você começar com uma lista de três itens e estendê-la com uma lista de outros três itens, terminará com uma lista de seis itens.
  3. Por outro lado, o método append() recebe um único argumento, que pode ser qualquer tipo de dados. Aqui, você está chamando o método append() com uma lista de três itens.
  4. Se você começar com uma lista de seis itens e anexar uma lista a ela, acabará com... uma lista de sete itens. Por que sete? Porque o último item (que você acabou de anexar) é uma lista. As listas podem conter qualquer tipo de dados, incluindo outras listas. Isso pode ser o que você deseja ou não. Mas é o que você pediu e é o que você conseguiu.

Pesquisa de valores em uma lista

>>> uma_lista = ['a', 'b', 'new', 'mpilgrim', 'new']
>>> uma_lista.count('new')       ①
2
>>> 'new' in uma_lista           ②
True
>>> 'c' in uma_lista
False
>>> uma_lista.index('mpilgrim')  ③
3
>>> uma_lista.index('new')       ④
2
>>> uma_lista.index('c')         ⑤
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
ValueError: list.index(x): x not in list
  1. Como você pode esperar, o método count() retorna o número de ocorrências de um valor específico em uma lista.
  2. Se tudo o que você deseja saber é se um valor está na lista ou não, o operador in é um pouco mais rápido do que usar o método count(). O operador in sempre retorna True ou False; ele não dirá quantas vezes o valor aparece na lista.
  3. Nem o operador in nem o método count() informarão onde um valor aparece na lista. Se você precisa saber em que lugar da lista está um valor, chame o método index(). Por padrão, ele pesquisará a lista inteira, embora você possa especificar um segundo argumento opcional do índice (baseado em 0) para começar, e até mesmo um terceiro argumento opcional do índice (baseado em 0) para parar a pesquisa.
  4. O método index() encontra a primeira ocorrência de um valor na lista. Nesse caso, ocorre 'new' duas vezes na lista, em uma_lista[2] e uma_lista[4], mas o método index() retornará apenas o índice da primeira ocorrência.
  5. Como você não pode esperar, se o valor não for encontrado na lista, o método index() gerará uma exceção.

Espere o que? Isso mesmo: o método index() levanta uma exceção se não encontrar o valor na lista. Isso é notavelmente diferente da maioria das linguagens, que retornará algum índice inválido (como -1). Embora isso possa parecer irritante no início, acho que você vai gostar. Isso significa que seu programa irá travar na origem do problema, em vez de falhar estranha e silenciosamente mais tarde. Lembre-se, -1 é um índice de lista válido. Se o método index() retornasse -1, isso poderia levar a algumas sessões de depuração não tão divertidas!

Removendo itens de uma lista

As listas nunca têm lacunas.

As listas podem se expandir e se contrair automaticamente. Você viu a parte da expansão. Existem várias maneiras diferentes de remover itens de uma lista também.

>>> uma_lista = ['a', 'b', 'new', 'mpilgrim', 'new']
>>> uma_lista[1]
'b'
>>> del uma_lista[1]         ①
>>> uma_lista
['a', 'new', 'mpilgrim', 'new']
>>> uma_lista[1]             ②
'new'
  1. Você pode usar a instrução del para excluir um item específico de uma lista.
  2. Acessando o índice 1 após a exclusão do índice 1 não resultar em um erro. Todos os itens após o item excluído mudam seu índice posicional para “preencher a lacuna” criada ao excluir o item.

Não sabe o índice posicional? Não é um problema; você pode remover itens por valor.

>>> uma_lista.remove('new')  ①
>>> uma_lista
['a', 'mpilgrim', 'new']
>>> uma_lista.remove('new')  ②
>>> uma_lista
['a', 'mpilgrim']
>>> uma_lista.remove('new')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: list.remove(x): x not in list
  1. Você também pode remover um item de uma lista com o método remove(). O método remove() pega um valor e remove a primeira ocorrência desse valor da lista. Novamente, todos os itens após o item excluído terão seus índices de posição reduzidos para "preencher a lacuna". As listas nunca têm lacunas.
  2. Você pode chamar o método remove() com a frequência que desejar, mas isso gerará uma exceção se você tentar remover um valor que não está na lista.

Removendo itens de uma lista: Rodada bônus

Outro método de lista interessante é o pop(). O método pop() é outra maneira de remover itens de uma lista, mas com uma diferença.

>>> uma_lista = ['a', 'b', 'new', 'mpilgrim']
>>> uma_lista.pop()   ①
'mpilgrim'
>>> uma_lista
['a', 'b', 'new']
>>> uma_lista.pop(1)  ②
'b'
>>> uma_lista
['a', 'new']
>>> uma_lista.pop()
'new'
>>> uma_lista.pop()
'a'
>>> uma_lista.pop()   ③
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: pop from empty list
  1. Quando chamado sem argumentos, o método pop() da lista remove o último item da lista e retorna o valor removido.
  2. Você pode destacar itens arbitrários de uma lista. Basta passar um índice posicional para o método pop(). Ele removerá esse item, mudará todos os itens posteriores para “preencher a lacuna” e retornará o valor removido.
  3. Chamar pop() numa lista vazia gera uma exceção.

Observação

Chamar o método pop() da lista sem um argumento é como a função pop() em Perl. Ele remove o último item da lista e retorna o valor do item removido. Perl tem outra função, shift(), que remove o primeiro item e retorna seu valor; em Python, isso é equivalente a uma_lista.pop(0).

Listas em um contexto booleano

Listas vazias são falsas; todas as outras listas são verdadeiras.

Você também pode usar uma lista em um contexto booleano, como uma instrução if.

>>> def eh_verdadeiro(qualquer_coisa):
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro([])             ①
não, é verdadeiro
>>> eh_verdadeiro(['a'])          ②
sim, é verdadeiro
>>> eh_verdadeiro([False])        ③
sim, é verdadeiro
  1. Em um contexto booleano, uma lista vazia é falsa.
  2. Qualquer lista com pelo menos um item é verdadeira.
  3. Qualquer lista com pelo menos um item é verdadeira. O valor dos itens é irrelevante.

Tuplas

Uma tupla é uma lista imutável. Uma tupla não pode ser alterada de nenhuma maneira depois de criada.

>>> a_tuple = ("a", "b", "mpilgrim", "z", "example")  ①
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple[0]                                        ②
'a'
>>> a_tuple[-1]                                       ③
'example'
>>> a_tuple[1:3]                                      ④
('b', 'mpilgrim')
  1. Uma tupla é definida da mesma maneira que uma lista, exceto que todo o set de elementos é colocado entre parênteses em vez de colchetes.
  2. Os elementos de uma tupla têm uma ordem definida, assim como uma lista. Os índices de tupla são baseados em zero, assim como uma lista, então o primeiro elemento de uma tupla não vazia é sempre a_tuple[0].
  3. Índices negativos contam a partir do final da tupla, assim como uma lista.
  4. O fatiamento também funciona, como uma lista. Ao fatiar uma lista, você obtém uma nova lista; quando você corta uma tupla, obtém uma nova tupla.

A principal diferença entre tuplas e listas é que as tuplas não podem ser alteradas. Em termos técnicos, as tuplas são imutáveis. Em termos práticos, eles não têm métodos que permitam alterá-los. Listas têm métodos como append(), extend(), insert(), remove(), e pop(). As tuplas não possuem nenhum desses métodos. Você pode fatiar uma tupla (porque isso cria uma nova tupla) e pode verificar se uma tupla contém um valor específico (porque isso não muda a tupla) e... é sobre isso.

# continuação do exemplo anterior
>>> a_tuple
('a', 'b', 'mpilgrim', 'z', 'example')
>>> a_tuple.append("new")               ①
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'append'
>>> a_tuple.remove("z")                 ②
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'remove'
>>> a_tuple.index("example")            ③
4
>>> "z" in a_tuple                      ④
True
  1. Você não pode adicionar elementos a uma tupla. Tuples não têm método append() ou extend().
  2. Você não pode remover elementos de uma tupla. Tuples não têm método remove() ou pop().
  3. Você pode encontrar elementos em uma tupla, pois isso não altera a tupla.
  4. Você também pode usar o operador in para verificar se um elemento existe na tupla.

Então, para que servem as tuplas?

  • Tuplas são mais rápidas do que listas. Se você está definindo um set constante de valores e tudo o que vai fazer com ele é iterar por ele, use uma tupla em vez de uma lista.
  • Isso torna seu código mais seguro se você “protege contra gravação” os dados que não precisam ser alterados. Usar uma tupla em vez de uma lista é como ter uma declaração assert implícita que mostra que esses dados são constantes e que um pensamento especial (e uma função específica) é necessário para substituí-lo.
  • Algumas tuplas podem ser usadas como chaves de dicionário (especificamente, tuplas que contêm valores imutáveis como strings, números e outras tuplas). As listas nunca podem ser usadas como chaves de dicionário, porque as listas não são imutáveis.

Observação

Tuplas podem ser convertidas em listas e vice-versa. A função tuple() embutida pega uma lista e retorna uma tupla com os mesmos elementos, e a função list() pega uma tupla e retorna uma lista. Na verdade, tuple() congela uma lista e list() descongela uma tupla.

Tuplas em um contexto booleano

Você pode usar tuplas em um contexto booleano, como uma instrução if.

>>> def eh_verdadeiro(qualquer_coisa):
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro(())             ①
não, é verdadeiro
>>> eh_verdadeiro(('a', 'b'))     ②
sim, é verdadeiro
>>> eh_verdadeiro((False,))       ③
sim, é verdadeiro
>>> type((False))                 ④
<class 'bool'>
>>> type((False,))
<class 'tuple'>
  1. Em um contexto booleano, uma tupla vazia é falsa.
  2. Qualquer tupla com pelo menos um item é verdadeira.
  3. Qualquer tupla com pelo menos um item é verdadeira. O valor dos itens é irrelevante. Mas o que aquela vírgula está fazendo aí?
  4. Para criar uma tupla de um item, você precisa de uma vírgula após o valor. Sem a vírgula, o Python apenas assume que você tem um par extra de parênteses, o que é inofensivo, mas não cria uma tupla.

Atribuição de vários valores de uma vez

Aqui está um atalho de programação legal: no Python, você pode usar uma tupla para atribuir vários valores de uma vez.

>>> v = ('a', 2, True)
>>> (x, y, z) = v       ①
>>> x
'a'
>>> y
2
>>> z
True
  1. v é uma tupla de três elementos e (x, y, z) é uma tupla de três variáveis. Atribuir um ao outro atribui cada um dos valores de v a cada uma das variáveis, em ordem.

Isso tem todos os tipos de uso. Suponha que você queira atribuir nomes a um intervalo de valores. Você pode usar a função range() incorporada com atribuição de várias variáveis ​​para atribuir rapidamente valores consecutivos.

>>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7)  ①
>>> MONDAY                                                                       ②
0
>>> TUESDAY
1
>>> SUNDAY
6
  1. A função range() embutida constrói uma sequência de inteiros. (Tecnicamente, a função range() retorna um iterador, não uma lista ou tupla, mas você aprenderá sobre essa distinção mais tarde.) MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, e SUNDAY são as variáveis ​​que você está definindo. (Este exemplo veio do módulo calendar, um pequeno módulo divertido que imprime calendários, como o programa UNIX cal. O módulo calendar define constantes inteiras para os dias da semana.)
  2. Agora, cada variável tem seu valor: MONDAY é 0, TUESDAY é 1 e assim por diante.

Você também pode usar a atribuição de várias variáveis para criar funções que retornam vários valores, simplesmente retornando uma tupla de todos os valores. O chamador pode tratá-lo como uma única tupla ou pode atribuir os valores a variáveis individuais. Muitas bibliotecas Python padrão fazem isso, incluindo o módulo os, sobre o qual você aprenderá no próximo capítulo.

Conjuntos (sets)

Um set é uma “bolsa” não ordenada de valores únicos. Um único set pode conter valores de qualquer tipo de dados imutável. Depois de ter dois sets, você pode fazer operações de set padrão, como união, interseção e diferença de set.

Criando um Conjunto

Primeiras coisas primeiro. Criar um set é fácil.

>>> um_conjunto = {1}     ①
>>> um_conjunto
{1}
>>> type(um_conjunto)     ②
<class 'set'>
>>> um_conjunto = {1, 2}  ③
>>> um_conjunto
{1, 2}
  1. Para criar um set com um valor, coloque o valor entre chaves ({}).
  2. Os sets são realmente implementados como classes, mas não se preocupe com isso por enquanto.
  3. Para criar um set com vários valores, separe os valores com vírgulas e envolva tudo com chaves.

Você também pode criar um set de uma lista.

>>> uma_lista = ['a', 'b', 'mpilgrim', True, False, 42]
>>> um_conjunto = set(uma_lista)                     ①
>>> um_conjunto                                      ②
{'a', False, 'b', True, 'mpilgrim', 42}
>>> uma_lista                                        ③
['a', 'b', 'mpilgrim', True, False, 42]
  1. Para criar um set a partir de uma lista, use a set()função. (Pedantes que sabem sobre como os sets são implementados irão apontar que isso não é realmente chamar uma função, mas instanciar uma classe. Eu prometo que você aprenderá a diferença mais tarde neste livro. Por enquanto, apenas saiba que isso set()atua como uma função, e ele retorna um set.)
  2. Como mencionei anteriormente, um único set pode conter valores de qualquer tipo de dados. E, como mencionei anteriormente, os sets não são ordenados . Este set não lembra a ordem original da lista que foi usada para criá-lo. Se você fosse adicionar itens a este set, ele não se lembraria da ordem em que você os adicionou.
  3. A lista original não foi alterada.

Ainda não tem valores? Não é um problema. Você pode criar um set vazio.

>>> um_conjunto = set()    ①
>>> um_conjunto            ②
set()
>>> type(um_conjunto)      ③
<class 'set'>
>>> len(um_conjunto)       ④
0
>>> not_sure = {}          ⑤
>>> type(not_sure)
<class 'dict'>
  1. Para criar um set vazio, chame set() sem argumentos.
  2. A representação impressa de um set vazio parece um pouco estranha. Você estava esperando {}, talvez? Isso denotaria um dicionário vazio, não um set vazio. Você aprenderá sobre dicionários posteriormente neste capítulo.
  3. Apesar da estranha representação impressa, este é um set…
  4. …E este set não tem membros.
  5. Devido a peculiaridades históricas transportadas do Python 2, você não pode criar um set vazio com duas chaves. Na verdade, isso cria um dicionário vazio, não um set vazio.

Modificando um set (Conjunto)

Existem duas maneiras diferentes de adicionar valores a um set existente: o método add() e o método update().

>>> um_conjunto = {1, 2}
>>> um_conjunto.add(4)  ①
>>> um_conjunto
{1, 2, 4}
>>> len(um_conjunto)    ②
3
>>> um_conjunto.add(1)  ③
>>> um_conjunto
{1, 2, 4}
>>> len(um_conjunto)    ④
3
  1. O método add() usa um único argumento, que pode ser qualquer tipo de dados, e adiciona o valor fornecido ao set.
  2. Este set agora tem 3 membros.
  3. Sets são bolsas de valores únicos. Se você tentar adicionar um valor que já existe no set, não fará nada. Não gerará um erro; é apenas um ambiente autônomo.
  4. Este set ainda tem 3 membros.
>>> um_conjunto = {1, 2, 3}
>>> um_conjunto
{1, 2, 3}
>>> um_conjunto.update({2, 4, 6})                       ①
>>> um_conjunto                                         ②
{1, 2, 3, 4, 6}
>>> um_conjunto.update({3, 6, 9}, {1, 2, 3, 5, 8, 13})  ③
>>> um_conjunto
{1, 2, 3, 4, 5, 6, 8, 9, 13}
>>> um_conjunto.update([10, 20, 30])                    ④
>>> um_conjunto
{1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
  1. O método update() pega um argumento, um set, e adiciona todos os seus membros ao set original. É como se você chamasse o método add() com cada membro do set.
  2. Valores duplicados são ignorados, pois os sets não podem conter duplicatas.
  3. Você pode realmente chamar o método update() com qualquer número de argumentos. Quando chamado com dois sets, o método update() adiciona todos os membros de cada set ao set original (eliminando duplicatas).
  4. O método update() pode pegar objetos de vários tipos de dados diferentes, incluindo listas. Quando chamado com uma lista, o método update() adiciona todos os itens da lista ao set original.

Removendo itens de um set

Existem três maneiras de remover valores individuais de um set. Os dois primeiros, discard() e remove(), têm uma diferença sutil.

>>> um_conjunto = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> um_conjunto
{1, 3, 36, 6, 10, 45, 15, 21, 28}
>>> um_conjunto.discard(10)                        ①
>>> um_conjunto
{1, 3, 36, 6, 45, 15, 21, 28}
>>> um_conjunto.discard(10)                        ②
>>> um_conjunto
{1, 3, 36, 6, 45, 15, 21, 28}
>>> um_conjunto.remove(21)                         ③
>>> um_conjunto
{1, 3, 36, 6, 45, 15, 28}
>>> um_conjunto.remove(21)                         ④
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 21
  1. O método discard() usa um único valor como argumento e remove esse valor do set.
  2. Se você chamar o método discard() com um valor que não existe no set, ele não fará nada. Sem erro; é apenas um ambiente autônomo.
  3. O método remove() também aceita um único valor como argumento e também remove esse valor do set.
  4. Aqui está a diferença: se o valor não existir no set, o método remove() gerará uma exceção KeyError.

Como as listas, os sets têm um método pop().

>>> um_conjunto = {1, 3, 6, 10, 15, 21, 28, 36, 45}
>>> um_conjunto.pop()                                ①
1
>>> um_conjunto.pop()
3
>>> um_conjunto.pop()
36
>>> um_conjunto
{6, 10, 45, 15, 21, 28}
>>> um_conjunto.clear()                              ②
>>> um_conjunto
set()
>>> um_conjunto.pop()                                ③
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'pop from an empty set'
  1. O método pop() remove um único valor de um set e retorna o valor. No entanto, como os sets não são ordenados, não há "último" valor em um set, portanto, não há como controlar qual valor é removido. É completamente arbitrário.
  2. O método clear() remove todos os valores de um set, deixando você com um set vazio. Isso é equivalente a um_conjunto = set(), o que criaria um novo set vazio e sobrescreveria o valor anterior da variável um_conjunto.
  3. A tentativa de retirar um valor de um set vazio levantará uma exceção KeyError.

Operações comuns com set (conjuntos)

O tipo set do Python oferece suporte a várias operações comuns com conjuntos.

>>> um_conjunto = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195}
>>> 30 in um_conjunto                                                     ①
True
>>> 31 in um_conjunto
False
>>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21}
>>> um_conjunto.union(b_set)                                              ②
{1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127}
>>> um_conjunto.intersection(b_set)                                       ③
{9, 2, 12, 5, 21}
>>> um_conjunto.difference(b_set)                                         ④
{195, 4, 76, 51, 30, 127}
>>> um_conjunto.symmetric_difference(b_set)                               ⑤
{1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
  1. Para testar se um valor é membro de um set, use o operador in. Isso funciona da mesma forma que listas.
  2. O método union() retorna um novo set contendo todos os elementos que estão em qualquer um dos sets.
  3. O método intersection() retorna um novo set contendo todos os elementos que estão em ambos os sets.
  4. O método difference() retorna um novo set contendo todos os elementos que estão em um_conjunto, mas não em b_set.
  5. O método symmetric_difference() retorna um novo set contendo todos os elementos que estão em exatamente um dos sets.

Três desses métodos são simétricos.

# continuação do exemplo anterior
>>> b_set.symmetric_difference(um_conjunto)                                             ①
{3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127}
>>> b_set.symmetric_difference(um_conjunto) == um_conjunto.symmetric_difference(b_set)  ②
True
>>> b_set.union(um_conjunto) == um_conjunto.union(b_set)                                ③
True
>>> b_set.intersection(um_conjunto) == um_conjunto.intersection(b_set)                  ④
True
>>> b_set.difference(um_conjunto) == um_conjunto.difference(b_set)                      ⑤
False
  1. A diferença simétrica de um_conjunto de b_set parece diferente da diferença simétrica de b_set de um_conjunto, mas lembre-se, os sets não são ordenados. Quaisquer dois sets que contenham todos os mesmos valores (sem nenhum restante) são considerados iguais.
  2. E é exatamente isso que acontece aqui. Não se deixe enganar pela representação impressa do Python Shell desses sets. Eles contêm os mesmos valores, portanto, são iguais.
  3. A união de dois sets também é simétrica.
  4. A interseção de dois sets também é simétrica.
  5. A diferença de dois sets não é simétrica. Isso faz sentido; é análogo a subtrair um número de outro. A ordem dos operandos é importante.

Finalmente, existem algumas perguntas que você pode fazer aos sets.

>>> um_conjunto = {1, 2, 3}
>>> b_set = {1, 2, 3, 4}
>>> um_conjunto.issubset(b_set)    ①
True
>>> b_set.issuperset(um_conjunto)  ②
True
>>> um_conjunto.add(5)             ③
>>> um_conjunto.issubset(b_set)
False
>>> b_set.issuperset(um_conjunto)
False
  1. um_conjunto é um subconjunto de b_set  - todos os membros de um_conjunto também são membros de b_set.
  2. Fazendo a mesma pergunta ao contrário, b_set é um superconjunto de um_conjunto, porque todos os membros de um_conjunto também são membros de b_set.
  3. Assim que você adiciona um valor a um_conjunto que não está em b_set, ambos os testes retornam False.

Conjuntos em um contexto booleano

Você pode usar sets em um contexto booleano, como uma instrução if.

>>> def eh_verdadeiro(qualquer_coisa):
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro(set())          ①
não, é verdadeiro
>>> eh_verdadeiro({'a'})          ②
sim, é verdadeiro
>>> eh_verdadeiro({False})        ③
sim, é verdadeiro
  1. Em um contexto booleano, um set vazio é falso.
  2. Qualquer set com pelo menos um item é verdadeiro.
  3. Qualquer set com pelo menos um item é verdadeiro. O valor dos itens é irrelevante.

Dicionários

Um dicionário é um set não ordenado de pares chave-valor. Ao adicionar uma chave a um dicionário, você também deve adicionar um valor para essa chave. (Você sempre pode alterar o valor posteriormente). Os dicionários Python são otimizados para recuperar o valor quando você conhece a chave, mas não o contrário.

Observação

Um dicionário em Python é como um hash em Perl 5. Em Perl 5, as variáveis que armazenam hashes sempre começam com um caractere %. No Python, as variáveis podem ter qualquer nome, e o Python rastreia o tipo de dados internamente.

Criando um Dicionário

Criar um dicionário é fácil. A sintaxe é semelhante a criação de sets, mas em vez de valores, você tem pares de chave-valores. Depois de ter um dicionário, você pode pesquisar os valores por sua chave.

>>> um_dicionario = {'server': 'db.diveintopython3.org', 'database': 'mysql'}  ①
>>> um_dicionario
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> um_dicionario['server']                                                    ②
'db.diveintopython3.org'
>>> um_dicionario['database']                                                  ③
'mysql'
>>> um_dicionario['db.diveintopython3.org']                                    ④
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'db.diveintopython3.org'
  1. Primeiro, você cria um novo dicionário com dois itens e o atribui à variável um_dicionario. Cada item é um par de chave-valores e todo o conjunto de itens está entre chaves.
  2. 'server' é uma chave e seu valor associado, referenciado por um_dicionario['server'], é 'db.diveintopython3.org'.
  3. 'database' é uma chave e seu valor associado, referenciado por um_dicionario['database'], é 'mysql'.
  4. Você pode obter valores por chave, mas não pode obter chaves por valor. Então um_dicionario['server'] é 'db.diveintopython3.org', mas um_dicionario['db.diveintopython3.org'] levanta uma exceção, porque 'db.diveintopython3.org' não é uma chave.

Modificando um Dicionário

Os dicionários não têm nenhum limite de tamanho predefinido. Você pode adicionar novos pares de chave-valores a um dicionário a qualquer momento ou pode modificar o valor de uma chave existente. Continuando com o exemplo anterior:

>>> um_dicionario
{'server': 'db.diveintopython3.org', 'database': 'mysql'}
>>> um_dicionario['database'] = 'blog'  ①
>>> um_dicionario
{'server': 'db.diveintopython3.org', 'database': 'blog'}
>>> um_dicionario['user'] = 'mark'      ②
>>> um_dicionario                       ③
{'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'}
>>> um_dicionario['user'] = 'dora'      ④
>>> um_dicionario
{'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
>>> um_dicionario['User'] = 'mark'      ⑤
>>> um_dicionario
{'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
  1. Você não pode ter chaves duplicadas em um dicionário. Atribuir um valor a uma chave existente apagará o valor antigo.
  2. Você pode adicionar novos pares de chave-valores a qualquer momento. Essa sintaxe é idêntica à modificação de valores existentes.
  3. O novo item do dicionário (chave 'user', valor 'mark') parece estar no meio. Na verdade, foi apenas uma coincidência que os itens parecessem estar em ordem no primeiro exemplo; é uma coincidência que eles pareçam estar fora de ordem agora.
  4. Atribuir um valor a uma chave de dicionário existente simplesmente substitui o valor antigo pelo novo.
  5. Isso mudará o valor da chave user de volta para "mark"? Não! Observe a chave de perto - é uma capital U em "User". As chaves de dicionário diferenciam maiúsculas de minúsculas, portanto, esta instrução está criando um novo par chave-valor, não substituindo um existente. Pode ser parecido com você, mas no que diz respeito ao Python, é completamente diferente.

Dicionários de valores mistos

Dicionários não são apenas para strings. Os valores do dicionário podem ser qualquer tipo de dados, incluindo inteiros, booleanos, objetos arbitrários ou até mesmo outros dicionários. E dentro de um único dicionário, os valores não precisam ser todos do mesmo tipo; você pode misturar e combinar conforme necessário. As chaves de dicionário são mais restritas, mas podem ser strings, inteiros e alguns outros tipos. Você também pode misturar e combinar os principais tipos de dados em um dicionário.

Na verdade, você já viu um dicionário com chaves e valores que não sejam strings, em seu primeiro programa Python.

SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
            1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}

Vamos separar isso no shell interativo.

>>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
...             1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
>>> len(SUFFIXES)      ①
2
>>> 1000 in SUFFIXES   ②
True
>>> SUFFIXES[1000]     ③
['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
>>> SUFFIXES[1024]     ④
['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
>>> SUFFIXES[1000][3]  ⑤
'TB'
  1. Como listas e sets, a função len() fornece o número de chaves em um dicionário.
  2. E como listas e sets, você pode usar o operador in para testar se uma chave específica está definida em um dicionário.
  3. 1000 é uma chave no dicionário SUFFIXES; seu valor é uma lista de oito itens (oito strings, para ser mais preciso).
  4. Da mesma forma, 1024 é uma chave no dicionário SUFFIXES; seu valor também é uma lista de oito itens.
  5. Como SUFFIXES[1000] é uma lista, você pode endereçar itens individuais na lista por seu índice baseado em 0.

Dicionários em um contexto booleano

Dicionários vazios são falsos; todos os outros dicionários são verdadeiros.

Você também pode usar um dicionário em um contexto booleano, como uma instrução if.

>>> def eh_verdadeiro(qualquer_coisa):
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro({})             ①
não, é verdadeiro
>>> eh_verdadeiro({'a': 1})       ②
sim, é verdadeiro
  1. Em um contexto booleano, um dicionário vazio é falso.
  2. Qualquer dicionário com pelo menos um par de chave-valores é verdadeiro.

None

None é uma constante especial em Python. É um valor nulo. None não é o mesmo que False. Nonenão é 0. None não é uma string vazia. Comparando None com qualquer coisa diferente de None sempre retornará False.

None é o único valor nulo. Ele tem seu próprio tipo de dados (NoneType). Você pode atribuir None a qualquer variável, mas não pode criar outros objetos NoneType. Todas as variáveis cujo valor é None são iguais entre si.

>>> type(None)
<class 'NoneType'>
>>> None == False
False
>>> None == 0
False
>>> None == ''
False
>>> None == None
True
>>> x = None
>>> x == None
True
>>> y = None
>>> x == y
True

None num contexto booleano

Em um contexto booleano, None é falso e not None é verdadeiro.

>>> def eh_verdadeiro(qualquer_coisa):
...   if qualquer_coisa:
...     print("sim, é verdadeiro")
...   else:
...     print("não, é verdadeiro")
...
>>> eh_verdadeiro(None)
não, é verdadeiro
>>> eh_verdadeiro(not None)
sim, é verdadeiro

Leitura Adicional

Esse artigo é uma tradução de um capítulo do livro "Dive Into Python 3" escrito por Mark Pilgrim. Você pode ler o livro desde o início em português clicando aqui.

Traduzido por Acervo Lima. O original pode ser acessado aqui.

Licença

sexta-feira, 7 de maio de 2021

Seu primeiro programa Python

❝Não enterre seu fardo em silêncio santo. Você tem um problema? Excelente. Alegre-se, mergulhe e investigue.❞
- Ven. Henepola Gunaratana

Mergulho

A convenção dita que devo aborrecê-lo com os blocos de construção fundamentais da programação, para que possamos trabalhar lentamente para construir algo útil. Vamos pular tudo isso. Aqui está um programa Python completo e funcional. Provavelmente não faz absolutamente nenhum sentido para você. Não se preocupe com isso, porque você vai dissecar linha por linha. Mas leia primeiro e veja o que você pode fazer com isso, se é que pode fazer alguma coisa.

SUFIXOS = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
           1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}

def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
    '''Converta um tamanho de arquivo em um formato legível.

    Argumentos keyword:
    tamanho -- tamanho do arquivo em bytes
    um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
                            if False, usa multiplos de 1000

    Retorna: string

    '''
    if tamanho < 0:
        raise ValueError('O número não deve ser negativo')

    multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000
    for sufixo in SUFIXOS[multiplo]:
        tamanho /= multiplo
        if tamanho < multiplo:
            return '{0:.1f} {1}'.format(tamanho, sufixo)

    raise ValueError('numero muito longo')

if __name__ == '__main__':
    print(tamanho_aproximado(1000000000000, False))
    print(tamanho_aproximado(1000000000000))

Agora vamos executar este programa na linha de comando. No Windows, será mais ou menos assim:

PS C:\Users\user\working\dive_into_python_3> & C:/Users/user/AppData/Local/Programs/Python/Python37/python.exe c:/Users/user/working/dive_into_python_3/teste.py 
1.0 TB
931.3 GiB

No Mac OS X ou Linux, seria algo assim:

you@localhost:~/diveintopython3/examples$ python3 teste.py
1.0 TB
931.3 GiB

O que acabou de acontecer? Você executou seu primeiro programa Python. Você chamou o interpretador Python na linha de comando e passou o nome do script que queria que o Python executasse. O script define uma única função, a função tamanho_aproximado(), que pega um tamanho de arquivo exato em bytes e calcula um tamanho “bonito” (mas aproximado). (Você provavelmente já viu isso no Windows Explorer, ou no Mac OS X Finder, ou Nautilus ou Dolphin ou Thunar no Linux. Se você exibir uma pasta de documentos como uma lista de várias colunas, será exibida uma tabela com o ícone do documento, o nome do documento, o tamanho, o tipo, a data da última modificação e assim por diante. Se a pasta contiver um arquivo de 1093 bytes denominado TODO, seu gerenciador de arquivos não será exibido TODO 1093 bytes; em vez disso, aparecerá algo como TODO 1 KB. Isso é o que a função tamanho_aproximado() faz).

Observe a parte inferior do script e você verá duas chamadas para print(tamanho_aproximado(arguments)). Essas são chamadas de função - primeiro chamando a função tamanho_aproximado() e passando uma série de argumentos, depois pegando o valor de retorno e passando-o direto para a função print(). A função print() é integrada; você nunca verá uma declaração explícita disso. Você pode simplesmente usá-la, a qualquer hora, em qualquer lugar. (Existem muitas funções integradas e muito mais funções que são separadas em módulos. Paciência, gafanhoto).

Então, por que a execução do script na linha de comando fornece sempre a mesma saída? Nós vamos chegar a isso. Primeiro, vamos examinar essa função tamanho_aproximado().

Declarando funções

Python tem funções como a maioria das outras linguagens, mas não tem arquivos de cabeçalho separados como C++ ou seções interface/implementation como Pascal. Quando você precisar de uma função, basta declará-la, assim:

def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):

A palavra-chave def inicia a declaração da função, seguida pelo nome da função, seguido pelos argumentos entre parênteses. Vários argumentos são separados por vírgulas.

Observe também que a função não define um tipo de dados de retorno. As funções Python não especificam o tipo de dados de seu valor de retorno; eles nem mesmo especificam se retornam ou não um valor. (Na verdade, toda função Python retorna um valor; se a função alguma vez executar uma instrução return, ela retornará esse valor; caso contrário, retornará None o valor nulo do Python).

Observação

Em algumas linguagens, as funções (que retornam um valor) começam com function, e as sub-rotinas (que não retornam um valor) começam com sub. Não há sub-rotinas em Python. Tudo é uma função, todas as funções retornam um valor (mesmo que seja None) e todas as funções começam com def.

A função tamanho_aproximado() leva os dois argumentos -  tamanho e um_kilobyte_eh_1024_bytes - mas nenhum dos argumentos especifica um tipo de dados. Em Python, as variáveis nunca são tipadas explicitamente. Python descobre que tipo é uma variável e mantém o controle dela internamente.

Observação

Em Java e outras linguagens tipadas estaticamente, você deve especificar o tipo de dados do valor de retorno da função e cada argumento da função. Em Python, você nunca especifica explicitamente o tipo de dados de nada. Com base no valor que você atribui, o Python rastreia o tipo de dados internamente.

Argumentos opcionais e nomeados

Python permite que argumentos de função tenham valores padrão; se a função for chamada sem o argumento, o argumento obterá seu valor padrão. Além disso, os argumentos podem ser especificados em qualquer ordem usando argumentos nomeados.

Vamos dar outra olhada na declaração da função tamanho_aproximado():

def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):

O segundo argumento, um_kilobyte_eh_1024_bytes, especifica um valor padrão igual a True. Isso significa que o argumento é opcional; você pode chamar a função sem ele e o Python agirá como se você tivesse chamado como a função passando o valor True para o segundo parâmetro.

Agora observe a parte inferior do script:

if __name__ == '__main__':
    print(tamanho_aproximado(1000000000000, False))   ①
    print(tamanho_aproximado(1000000000000))          ②
  1. Isso chama a função tamanho_aproximado() com dois argumentos. Dentro da função tamanho_aproximado(), um_kilobyte_eh_1024_bytes será False, já que você passou explicitamente False como o segundo argumento.

  2. Isso chama a função tamanho_aproximado() com apenas um argumento. Mas tudo bem, porque o segundo argumento é opcional! Como o chamador não especifica, o segundo argumento é padronizado (True), conforme definido pela declaração da função.

Você também pode passar valores para uma função por nome.

Observação

teste é o nome do nosso script python. Execute o shell python na pasta onde o arquivo teste.py foi salvo.

Por exemplo: No PowerShell (windows), terminal (Linux, Mac) execute esses comando: cd caminho_da_pasta.
Exemplo PowerShell: cd C:\Users\dive_into_python_3; No terminal: cd /home/user/dive_into_python_3.

>>> from teste import tamanho_aproximado
>>> tamanho_aproximado(4000, um_kilobyte_eh_1024_bytes=False)           ①
'4.0 KB'
>>> tamanho_aproximado(tamanho=4000, um_kilobyte_eh_1024_bytes=False)   ②
'4.0 KB'
>>> tamanho_aproximado(um_kilobyte_eh_1024_bytes=False, tamanho=4000)   ③
'4.0 KB'
>>> tamanho_aproximado(um_kilobyte_eh_1024_bytes=False, 4000)           ④
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> tamanho_aproximado(tamanho=4000, False)                             ⑤
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
  1. Isso chama a função tamanho_aproximado() passando o valor 4000 para o primeiro argumento (tamanho) e False para o argumento denominado um_kilobyte_eh_1024_bytes. (Esse é o segundo argumento, mas não importa, como você verá em um minuto).

  2. Isso chama a funçãotamanho_aproximado() passando o valor 4000 para o argumento denominado tamanho e False para o argumento denominado um_kilobyte_eh_1024_bytes. (Esses argumentos nomeados estão na mesma ordem que os argumentos listados na declaração da função, mas isso também não importa).

  3. Isso chama a função tamanho_aproximado() passando o valor False para o argumento denominado um_kilobyte_eh_1024_bytes e 4000 para o argumento denominado tamanho. (Viu? Eu disse que a ordem não importava).

  4. Essa chamada falha, porque você tem um argumento nomeado seguido por um argumento não nomeado (posicional) e isso nunca funciona. Lendo a lista de argumentos da esquerda para a direita, uma vez que você tenha um único argumento nomeado, o restante dos argumentos também deve ser nomeado.

  5. Esta chamada também falha, pelo mesmo motivo da chamada anterior. Isso é surpreendente? Afinal, você passou 4000 para o argumento nomeado tamanho, então “obviamente” esse valor False era para o argumento um_kilobyte_eh_1024_bytes. Mas Python não funciona assim. Assim que você tiver um argumento nomeado, todos os argumentos à direita dele também precisam ser argumentos nomeados.

Escrevendo código legível

Não vou aborrecê-lo com um longo discurso de abanar o dedo sobre a importância de documentar seu código. Saiba que o código é escrito uma vez, mas lido muitas vezes, e o público mais importante para o seu código é você mesmo, seis meses depois de escrevê-lo (ou seja, depois que você esqueceu tudo, mas precisa consertar algo). Python facilita a escrita de código legível, então tire proveito disso. Você vai me agradecer em seis meses.

Strings de documentação

Você pode documentar uma função Python fornecendo a ela uma string de documentação (docstring para abreviar). Neste programa, a função tamanho_aproximado() possui uma docstring:

def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True):
    '''Converta um tamanho de arquivo em um formato legível.

    Argumentos keyword:
    tamanho -- tamanho do arquivo em bytes
    um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
                                 if False, usa multiplos de 1000

    Retorna: string

    '''

Cada função merece uma docstring decente.

As aspas triplas significam uma string de várias linhas. Tudo entre as aspas iniciais e finais faz parte de uma única string, incluindo retornos de carro, espaço em branco inicial e outros caracteres de aspas. Você pode usá-los em qualquer lugar, mas verá que são usados ​​com mais frequência ao definir uma docstring.

Observação

As aspas triplas também são uma maneira fácil de definir uma string com aspas simples e duplas, como qq/.../ no Perl 5.

Tudo o que está entre as aspas triplas é da docstring da função, que documenta o que a função faz. A docstring, se existir, deve ser a primeira coisa definida em uma função (ou seja, na próxima linha após a declaração da função). Tecnicamente, você não precisa atribuir um valor à sua docstring da função, mas sempre deve. Eu sei que você já ouviu isso em todas as aulas de programação que já fez, mas o Python oferece um incentivo adicional: A docstring está disponível em tempo de execução como um atributo da função.

Observação

Muitas IDEs Python usam a docstring para fornecer documentação sensível ao contexto, de forma que quando você digita o nome de uma função, a docstring aparece como uma dica de ferramenta. Isso pode ser extremamente útil, mas é tão bom quanto a docstring que você escreve.

O Caminho de Pesquisa import

Antes de prosseguir, quero mencionar brevemente o caminho de pesquisa da biblioteca. Python procura em vários lugares quando você tenta importar um módulo. Especificamente, ele procura em todos os diretórios definidos em sys.path. Esta é apenas uma lista e você pode facilmente visualizá-la ou modificá-la com métodos de lista padrão. (Você aprenderá mais sobre listas em tipos de dados nativos).

>>> import sys                                                 ①
>>> sys.path                                                   ②
['', 
 '/usr/lib/python31.zip', 
 '/usr/lib/python3.1',
 '/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@', 
 '/usr/lib/python3.1/lib-dynload', 
 '/usr/lib/python3.1/dist-packages', 
 '/usr/local/lib/python3.1/dist-packages']
>>> sys                                                        ③
<module 'sys' (built-in)>
>>> sys.path.insert(0, '/home/mark/diveintopython3/examples')  ④
>>> sys.path                                                   ⑤
['/home/mark/diveintopython3/examples', 
 '', 
 '/usr/lib/python31.zip', 
 '/usr/lib/python3.1', 
 '/usr/lib/python3.1/plat-linux2@EXTRAMACHDEPPATH@', 
 '/usr/lib/python3.1/lib-dynload', 
 '/usr/lib/python3.1/dist-packages', 
 '/usr/local/lib/python3.1/dist-packages']
  1. A importação do módulo sys disponibiliza todas as suas funções e atributos.

  2. sys.path é uma lista de nomes de diretório que constituem o caminho de pesquisa atual. (O seu terá uma aparência diferente, dependendo do seu sistema operacional, da versão do Python que você está executando e de onde foi instalado originalmente). O Python procurará nesses diretórios (nesta ordem) um arquivo .py cujo nome corresponda ao que você está tentando importar.

  3. Na verdade, eu menti; a verdade é mais complicada do que isso, porque nem todos os módulos são armazenados como arquivos .py. Alguns são módulos integrados; eles são realmente embutidos no próprio Python. Módulos integrados se comportam como módulos regulares, mas seu código-fonte Python não está disponível, porque eles não são escritos em Python! (Como o próprio Python, esses módulos integrados são escritos em C).
  4. Você pode adicionar um novo diretório ao caminho de pesquisa do Python em tempo de execução, adicionando o nome do diretório a sys.path, e o Python também procurará nesse diretório, sempre que você tentar importar um módulo. O efeito dura enquanto o Python estiver em execução.

  5. Ao usar sys.path.insert(0, new_path), você inseriu um novo diretório como o primeiro item da lista sys.path e, portanto, no início do caminho de pesquisa do Python. Quase sempre é isso que você deseja. Em caso de conflitos de nomenclatura (por exemplo, se Python vem com a versão 2 de uma biblioteca específica, mas você deseja usar a versão 3), isso garante que seus módulos serão encontrados e usados ​​em vez dos módulos que vieram com Python.

Tudo é um objeto

Caso você tenha perdido, eu acabei de dizer que as funções do Python têm atributos e que esses atributos estão disponíveis em tempo de execução. Uma função, como tudo o mais em Python, é um objeto.

Execute o shell Python interativo e siga em frente:

>>> import teste                                   ①
>>> print(teste.tamanho_aproximado(4096, True))    ②
4.0 KiB
>>> print(teste.tamanho_aproximado.__doc__)        ③
Converta um tamanho de arquivo em um formato legível.

    Argumentos keyword:
    tamanho -- tamanho do arquivo em bytes
    um_kilobyte_eh_1024_bytes -- if True (padrão), usa multiplos de 1024
                                 if False, usa multiplos de 1000

    Retorna: string
  1. A primeira linha importa o programa teste como um módulo - um pedaço de código que você pode usar interativamente ou de um programa Python maior. Depois de importar um módulo, você pode fazer referência a qualquer uma de suas funções, classes ou atributos públicos. Os módulos podem fazer isso para acessar a funcionalidade em outros módulos, e você também pode fazer isso no shell interativo do Python. Este é um conceito importante, e você verá muito mais dele ao longo deste livro.

  2. Quando você deseja usar funções definidas em módulos importados, você precisa incluir o nome do módulo. Então você não pode simplesmente dizer tamanho_aproximado; deve ser teste.tamanho_aproximado. Se você usou classes em Java, isso deve parecer vagamente familiar.

  3. Em vez de chamar a função como você esperava, solicitou um dos atributos da função, __doc__.

Observação

import em Python é como require em Perl. Depois de criar um módulo Python, você acessa suas funções com module.function; uma vez que você precisa de um módulo Perl, você acessa suas funções com module::function.

O que é um objeto?

Tudo em Python é um objeto e tudo pode ter atributos e métodos. Todas as funções têm um atributo __doc__ embutido, que retorna a docstring definida no código-fonte da função. O módulo sys é um objeto que possui (entre outras coisas) um atributo denominado path. E assim por diante.

Ainda assim, isso não responde à questão mais fundamental: o que é um objeto? Diferentes linguagens de programação definem “objeto” de maneiras diferentes. Em alguns, significa que todos os objetos devem ter atributos e métodos; em outros, significa que todos os objetos são subclassíveis. Em Python, a definição é mais ampla. Alguns objetos não têm atributos nem métodos, mas poderiam. Nem todos os objetos são subclassíveis. Mas tudo é um objeto no sentido de que pode ser atribuído a uma variável ou passado como um argumento para uma função.

Você pode ter ouvido o termo “objeto de primeira classe” em outros contextos de programação. Em Python, funções são objetos de primeira classe. Você pode passar uma função como um argumento para outra função. Módulos são objetos de primeira classe. Você pode passar um módulo inteiro como um argumento para uma função. As classes são objetos de primeira classe e as instâncias individuais de uma classe também são objetos de primeira classe.

Isso é importante, então vou repeti-lo caso você tenha perdido nas primeiras vezes: tudo em Python é um objeto. Strings são objetos. Listas são objetos. Funções são objetos. As classes são objetos. As instâncias de classe são objetos. Mesmo os módulos são objetos.

Indentação de código

As funções Python não têm begin ou explícito end e nem chaves para marcar onde o código da função começa e termina. O único delimitador é dois pontos (:) e o recuo do próprio código.

def tamanho_aproximado(tamanho, um_kilobyte_eh_1024_bytes=True): ①
    if tamanho < 0:                                              ②
        raise ValueError('O número não deve ser negativo')       ③
                                                                 ④
    multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000
    for sufixo in SUFIXOS[multiplo]:                             ⑤
        tamanho /= multiplo
        if tamanho < multiplo:
            return '{0:.1f} {1}'.format(tamanho, sufixo)

    raise ValueError('numero muito longo')
  1. Os blocos de código são definidos por sua indentação. Por “bloco de código”, quero dizer funções, instruções if, loops for, loops while e assim por diante. A indentação inicia um bloco e a desindentação o finaliza. Não há chaves, colchetes ou palavras-chave explícitas. Isso significa que o espaço em branco é significativo e deve ser consistente. Neste exemplo, o código da função tem quatro espaços indentados. Não precisa ter quatro espaços, só precisa ser consistente. A primeira linha sem recuo marca o fim da função.

  2. Em Python, uma instrução if é seguida por um bloco de código. Se a instrução if for avaliada como verdadeira, o bloco recuado é executado, caso contrário, cai para o bloco else (se houver). Observe a falta de parênteses ao redor da expressão.

  3. Esta linha está dentro do bloco de código if. Esta instrução raise gerará uma exceção (do tipo ValueError), mas somente se tamanho < 0.

  4. Este não é o fim da função. Linhas completamente em branco não contam. Eles podem tornar o código mais legível, mas não contam como delimitadores de bloco de código. A função continua na próxima linha.

  5. O loop for também marca o início de um bloco de código. Os blocos de código podem conter várias linhas, desde que todos tenham o mesmo recuo. Este loop for contém três linhas de código. Não há nenhuma outra sintaxe especial para blocos de código de várias linhas. Apenas recue e continue com sua vida.

Depois de alguns protestos iniciais e várias analogias maliciosas com o Fortran, você fará as pazes com isso e começará a ver seus benefícios. Um grande benefício é que todos os programas Python são semelhantes, já que o recuo é um requisito da linguagem e não uma questão de estilo. Isso torna mais fácil ler e entender o código Python de outras pessoas.

Observação

Python usa retornos de carro para separar instruções e dois pontos e indentação para separar blocos de código. C++ e Java usam ponto-e-vírgula para separar instruções e chaves para separar blocos de código.

Exceções

As exceções estão em todos os lugares em Python. Praticamente todos os módulos da biblioteca Python padrão os usam, e o próprio Python os criará em muitas circunstâncias diferentes. Você os verá repetidamente ao longo deste livro.

O que é uma exceção? Normalmente é um erro, uma indicação de que algo deu errado. (Nem todas as exceções são erros, mas não importa por enquanto). Algumas linguagens de programação incentivam o uso de códigos de retorno de erro, que você verifica. Python incentiva o uso de exceções, com as quais você lida.

Quando ocorre um erro no Python Shell, ele imprime alguns detalhes sobre a exceção e como ela aconteceu, e pronto. Isso é chamado de exceção não tratada. Quando a exceção foi levantada, não havia código para notá-la explicitamente e lidar com ela, então ela borbulhou seu caminho de volta ao nível superior do Python Shell, que cospe algumas informações de depuração e o encerrou. No shell, isso não é grande coisa, mas se isso acontecesse enquanto seu programa Python real estivesse em execução, todo o programa iria parar bruscamente se nada tratasse da exceção. Talvez seja isso que você queira, talvez não.

Observação

Ao contrário do Java, as funções Python não declaram quais exceções podem gerar. Depende de você determinar quais possíveis exceções você precisa detectar.

No entanto, uma exceção não precisa resultar em um travamento completo do programa. As exceções podem ser tratadas. Às vezes, uma exceção é realmente porque você tem um bug em seu código (como acessar uma variável que não existe), mas às vezes uma exceção é algo que você pode antecipar. Se você estiver abrindo um arquivo, ele pode não existir. Se você estiver importando um módulo, ele pode não estar instalado. Se você estiver se conectando a um banco de dados, ele pode não estar disponível ou você pode não ter as credenciais de segurança corretas para acessá-lo. Se você sabe que uma linha de código pode gerar uma exceção, deve tratar a exceção usando um bloco try...except.

Observação

Python usa blocos try...except para lidar com exceções e a instrução raise para gerá-las. Java e C++ usam blocos try...catch para lidar com exceções e a instrução throw para gerá-los.

A função tamanho_aproximado() levanta exceções em dois casos diferentes: se o tamanho fornecido for maior do que a função foi projetada para lidar ou se for menor que zero.

if tamanho < 0:
    raise ValueError('O número não deve ser negativo')

A sintaxe para gerar uma exceção é bastante simples. Use a instrução raise, seguida pelo nome da exceção e uma string opcional legível para fins de depuração. A sintaxe lembra a chamada de uma função. (Na realidade, as exceções são implementadas como classes, e essa instrução raise está, na verdade, criando uma instância da classe ValueError e passando a string 'O número não deve ser negativo' para seu método de inicialização. Mas estamos nos adiantando!)

Observação

Você não precisa lidar com uma exceção na função que a gera. Se uma função não lida com isso, a exceção é passada para a função de chamada, a função de chamada dessa função e assim por diante "na pilha". Se a exceção nunca for tratada, seu programa irá travar, o Python imprimirá um “traceback” para o erro padrão e ponto final. Novamente, talvez seja isso que você deseja; depende do que seu programa faz.

Captura de erros de importação

Uma das exceções integradas do Python é ImportError, que é gerada quando você tenta importar um módulo e falha. Isso pode acontecer por vários motivos, mas o caso mais simples é quando o módulo não existe em seu caminho de pesquisa de importação. Você pode usar isso para incluir recursos opcionais em seu programa. Por exemplo, a biblioteca chardet fornece detecção automática de codificação de caracteres. Talvez o seu programa queira usar esta biblioteca, se ela existir, mas continue normalmente se o usuário não a tiver instalado. Você pode fazer isso com um bloco try..except.

try:
    import chardet
except ImportError:
    chardet = None

Posteriormente, você pode verificar a presença do módulo chardet com uma instrução if simples:

if chardet:
  # faça algo
else:
  # continue de qualquer jeito

Outro uso comum da exceção ImportError é quando dois módulos implementam uma API comum, mas um é mais desejável do que o outro. (Talvez seja mais rápido ou use menos memória). Você pode tentar importar um módulo, mas voltar para um módulo diferente se a primeira importação falhar. Por exemplo, o capítulo XML fala sobre dois módulos que implementam uma API comum, chamada API ElementTree. O primeiro lxml é um módulo de terceiros que você precisa fazer o download e instalar por conta própria. O segundo, xml.etree.ElementTree é mais lento, mas faz parte da biblioteca padrão do Python 3.

try:
    from lxml import etree
except ImportError:
    import xml.etree.ElementTree as etree

Ao final deste try..exceptbloco, você importou algum módulo e o nomeou etree . Uma vez que ambos os módulos implementam uma API comum , o resto do seu código não precisa ficar verificando qual módulo foi importado. E uma vez que o módulo que foi importado é sempre chamado de etree , o resto do seu código não precisa estar cheio de ifinstruções para chamar módulos com nomes diferentes.

Variáveis não definidas

Dê uma outra olhada nesta linha de código da função tamanho_aproximado():

multiplo = 1024 if um_kilobyte_eh_1024_bytes else 1000

Você nunca declara a variável multiplo, apenas atribuiu um valor a ela. Tudo bem, porque Python permite que você faça isso. O que Python não vai permitirá que você faça referência a uma variável à qual nunca foi atribuído um valor. Tentar fazer isso gerará uma exceção NameError.

>>> x
Traceback (most recent call last):
  File "<stdin≷", line 1, in <module≷
NameError: name 'x' is not defined
>>> x = 1
>>> x
1

Você vai agradecer ao Python por isso um dia.

Tudo diferencia maiúsculas de minúsculas

Todos os nomes em Python diferenciam maiúsculas de minúsculas: nomes de variáveis, nomes de funções, nomes de classes, nomes de módulos, nomes de exceções. Se você puder obtê-lo, configurá-lo, chamá-lo, construí-lo, importá-lo ou aumentá-lo, ele diferencia maiúsculas de minúsculas.

≷≷≷ um_inteiro = 1
≷≷≷ um_inteiro
1
≷≷≷ UM_INTEIRO
Traceback (most recent call last):
  File "<stdin≷", line 1, in <module≷
NameError: name 'UM_INTEIRO' is not defined
≷≷≷ Um_Inteiro
Traceback (most recent call last):
  File "<stdin≷", line 1, in <module≷
NameError: name 'Um_Inteiro' is not defined
≷≷≷ um_inTeiro
Traceback (most recent call last):
  File "<stdin≷", line 1, in <module≷
NameError: name 'um_inTeiro' is not defined

E assim por diante.

Executando Scripts

Tudo em Python é um objeto.

Módulos Python são objetos e têm vários atributos úteis. Você pode usar isso para testar facilmente seus módulos à medida que os escreve, incluindo um bloco especial de código que é executado quando você executa o arquivo Python na linha de comando. Pegue as últimas linhas de teste.py:

if __name__ == '__main__':
    print(tamanho_aproximado(1000000000000, False))
    print(tamanho_aproximado(1000000000000))

Observação

Como C, Python usa == para comparação e = para atribuição. Ao contrário de C, Python não oferece suporte para atribuição in-line, portanto, não há chance de atribuir acidentalmente o valor que você pensou que estava comparando.

Então, o que torna esta declaração if especial? Bem, os módulos são objetos e todos os módulos têm um atributo __name__ embutido. Um módulo __name__ depende de como você está usando o módulo. Se você for importar o módulo, então __name__ será o nome do arquivo do módulo, sem um caminho de diretório ou extensão de arquivo.

>>> import teste
>>> teste.__name__
'teste'

Mas você também pode executar o módulo diretamente como um programa independente; nesse caso __name__, será um valor padrão especial: __main__. Python avaliará essa instrução if, encontrará uma expressão verdadeira e executará o bloco de código if. Neste caso, para imprimir dois valores.

c:\home\diveintopython3> c:\python31\python.exe humansize.py
1.0 TB
931.3 GiB

E esse é o seu primeiro programa Python!

Leitura Adicional

Esse artigo é uma tradução de um capítulo do livro "Dive Into Python 3" escrito por Mark Pilgrim. Você pode ler o livro desde o início em português clicando aqui.

Traduzido por Acervo Lima. O original pode ser acessado aqui.

Licença

Instalando o Python

Tempora mutantur nos et mutamur in illis. (Os tempos mudam e nós mudamos com eles.)
- antigo provérbio romano.

Mergulho

Antes de começar a programar em Python 3, você precisa instalá-lo.

Qual Python é certo para você?

Se você estiver usando uma conta em um servidor hospedado, seu ISP pode já ter instalado o Python 3. Se você estiver executando o Linux em casa, também pode ter o Python 3. As distribuições GNU/Linux mais populares vêm com o Python 3 na instalação padrão; O Mac OS X inclui uma versão de linha de comando do Python 3. O Microsoft Windows não vem com nenhuma versão do Python. Mas não se desespere! Você pode apontar e clicar para instalar o Python, independentemente do sistema operacional que tiver.

A maneira mais fácil de verificar o Python 3 em seu sistema Linux ou Mac OS X é a partir da linha de comando. Quando estiver em um prompt de linha de comando, basta digitar python3(tudo em minúsculas, sem espaços), pressionar ENTER e veja o que acontece. No meu sistema Linux doméstico, o Python 3.9 já está instalado e este comando me leva ao shell interativo do Python.

[thor@fedora ~]$ python
Python 3.9.4 (default, Apr  6 2021, 00:00:00) 
[GCC 11.0.1 20210324 (Red Hat 11.0.1-0)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

(Digite exit() e pressione ENTER para sair do shell interativo do Python.)

Meu provedor de hospedagem na web também executa Linux e fornece acesso de linha de comando, mas meu servidor não tem o Python 3 instalado. (Vaia!)

mark@manganese:~$ python3
bash: python3: command not found

Então, de volta à pergunta que deu início a esta seção, "Qual Python é o certo para você?" O que for executado no computador que você já possui.

[Leia as instruções do Windows ou pule para Instalação no Mac OS X, Instalação no Ubuntu Linux ou Instalação em outras plataformas.]

Instalando no Microsoft Windows

O Windows vem em duas arquiteturas atualmente: 32 bits e 64 bits. Claro, existem muitas versões diferentes do Windows - XP, Vista, Windows 7 - mas o Python roda em todas elas. A distinção mais importante é 32 bits x 64 bits. Se você não tem ideia de qual arquitetura está executando, provavelmente é de 64 bits.

Visite python.org/download/ e baixe o instalador do Windows Python 3 apropriado para sua arquitetura. Suas escolhas serão mais ou menos assim:

  • Instalador do Windows Python 3.1 (binário do Windows - não inclui o código-fonte)
  • Instalador do Python 3.1 Windows AMD64 (binário Windows AMD64 - não inclui o código-fonte)

Não quero incluir links diretos para download aqui, porque pequenas atualizações do Python acontecem o tempo todo e não quero ser responsável por você perder atualizações importantes. Você deve sempre instalar a versão mais recente do Python 3.x, a menos que tenha algum motivo esotérico para não fazê-lo.

  1. [Caixa de diálogo do Windows: aviso de segurança de arquivo aberto]

    Quando o download for concluído, clique duas vezes no arquivo .msi. O Windows exibirá um alerta de segurança, já que você está prestes a executar um código executável. O instalador oficial do Python é assinado digitalmente pela Python Software Foundation, a corporação sem fins lucrativos que supervisiona o desenvolvimento do Python. Não aceite imitações!

    Clique no botão Run para iniciar o instalador do Python 3.

  2. [Instalador Python: selecione se deseja instalar o Python 3.1 para todos os usuários deste computador]

    A primeira pergunta que o instalador fará é se você deseja instalar o Python 3 para todos os usuários ou apenas para você. A opção padrão é “instalar para todos os usuários”, que é a melhor escolha, a menos que você tenha um bom motivo para escolher o contrário. (Uma possível razão pela qual você desejaria “instalar apenas para mim” é que você está instalando o Python no computador da sua empresa e não tem direitos administrativos na sua conta do Windows. Mas então, por que você está instalando o Python sem a permissão do seu administrador do Windows da empresa? Não me coloque em apuros!)

    Clique no botão Next para aceitar sua escolha do tipo de instalação.

  3. [Instalador Python: selecione o diretório de destino]

    Em seguida, o instalador solicitará que você escolha um diretório de destino. O padrão para todas as versões do Python 3.1.x é C:\Python31\, que deve funcionar bem para a maioria dos usuários, a menos que você tenha um motivo específico para alterá-lo. Se você mantiver uma letra de unidade separada para a instalação de aplicativos, poderá navegar até ela usando os controles incorporados ou simplesmente digitar o nome do caminho na caixa abaixo. Você não está limitado a instalar o Python na unidade C:; você pode instalá-lo em qualquer unidade, em qualquer pasta.

    Clique no botão Next para aceitar sua escolha de diretório de destino.

  4. [Instalador Python: personalizar Python 3.1]

    A próxima página parece complicada, mas não é. Como muitos instaladores, você tem a opção de não instalar todos os componentes do Python 3. Se o espaço em disco for especialmente apertado, você pode excluir certos componentes.

    • Registrar extensões permite clicar duas vezes em arquivos de scripts Python ( .py) e executá-los. Recomendado, mas não obrigatório. (Esta opção não requer nenhum espaço em disco, portanto, não vale a pena excluí-la.)
    • Tcl/Tk é a biblioteca gráfica usada pelo Python Shell, que você usará ao longo deste livro. Eu recomendo fortemente manter esta opção.
    • A documentação instala um arquivo de ajuda que contém muitas das informações sobre docs.python.org. Recomendado se você estiver usando uma conexão discada ou tiver acesso limitado à Internet.
    • Os scripts de utilitários incluem o script 2to3.py sobre o qual você aprenderá mais adiante neste livro. Obrigatório se você quiser aprender como migrar o código Python 2 existente para o Python 3. Se você não tiver nenhum código Python 2 existente, pode pular esta opção.
    • Test Suite é uma coleção de scripts usados ​​para testar o próprio interpretador Python. Não o usaremos neste livro, nem nunca o usei no curso de programação em Python. Totalmente opcional.
  5. [Instalador Python: requisitos de espaço em disco]

    Se você não tiver certeza de quanto espaço em disco possui, clique no botão Disk Usage. O instalador listará as letras das unidades, calculará quanto espaço está disponível em cada unidade e calculará quanto sobraria após a instalação.

    Clique no botão OK para retornar à página “Customizing Python”.

  6. [Instalador Python: remover a opção Test Suite irá economizar 7908 KB no seu disco rígido]

    Se você decidir excluir uma opção, selecione o botão suspenso antes da opção e selecione “Todo o recurso ficará indisponível”. Por exemplo, a exclusão do conjunto de testes economizará incríveis 7908 KB de espaço em disco.

    Clique no botão Next para aceitar sua escolha de opções.

  7. [Instalador Python: medidor de progresso]

    O instalador irá copiar todos os arquivos necessários para o diretório de destino escolhido. (Isso acontece tão rapidamente que eu tive que tentar três vezes até mesmo para obter uma captura de tela!)

  8. [Instalador Python: instalação concluída.  Agradecimentos especiais do Windows a Mark Hammond, sem cujos anos de experiência em Windows livremente compartilhada, Python para Windows ainda seria Python para DOS.]

    Clique no botão Finish para sair do instalador.

  9. [Windows Python Shell, um shell gráfico interativo para Python]

    Em seu menu Start, deve haver um novo item chamado Python 3.1. Dentro dele, existe um programa chamado IDLE . Selecione este item para executar o Python Shell interativo.

[Pule para o uso do Python Shell]

Instalando no Mac OS X

Todos os computadores Macintosh modernos usam o chip Intel (como a maioria dos PCs com Windows). Macs mais antigos usavam chips PowerPC. Você não precisa entender a diferença, porque há apenas um instalador Mac Python para todos os Macs.

Visite https://python.org/download/ e baixe o instalador do Mac. Ele será chamado de algo como Python 3.1 Mac Installer Disk Image, embora o número da versão possa variar. Certifique-se de baixar a versão 3.x, não 2.x.

  1. [conteúdo da imagem do disco do instalador Python]

    Seu navegador deve montar automaticamente a imagem de disco e abrir uma janela do Finder para mostrar o conteúdo. (Se isso não acontecer, você terá que encontrar a imagem de disco em seus downloads e clique duas vezes para montá-lo. Ele será nomeado algo como python-3.1.dmg.) A imagem de disco contém uma série de arquivos de texto (Build.txt, License.txt, ReadMe.txt), e o pacote de instalação real Python.mpkg.

    Clique duas vezes no Python.mpkgpacote do instalador para iniciar o instalador do Mac Python.

  2. [Instalador Python: tela de boas-vindas]

    A primeira página do instalador fornece uma breve descrição do próprio Python e, em seguida, indica o arquivo ReadMe.txt (que você não leu, não é?) Para obter mais detalhes.

    Clique no botão Continue para avançar.

  3. [Instalador Python: informações sobre arquiteturas compatíveis, espaço em disco e pastas de destino aceitáveis]

    A próxima página contém algumas informações importantes: Python requer Mac OS X 10.3 ou posterior. Se ainda estiver executando o Mac OS X 10.2, você realmente deve atualizar. A Apple não fornece mais atualizações de segurança para o seu sistema operacional e o seu computador provavelmente estará em risco se você ficar online. Além disso, você não pode executar o Python 3.

    Clique no botão Continue para avançar.

  4. [Instalador Python: contrato de licença de software]

    Como todos os bons instaladores, o instalador Python exibe o contrato de licença do software. Python é open source e sua licença é aprovada pela Open Source Initiative. Python teve vários proprietários e patrocinadores ao longo de sua história, cada um dos quais deixou sua marca na licença do software. Mas o resultado final é o seguinte: Python é open source e você pode usá-lo em qualquer plataforma, para qualquer propósito, sem taxa ou obrigação de reciprocidade.

    Clique no botão Continue mais uma vez.

  5. [Instalador Python: caixa de diálogo para aceitar o contrato de licença]

    Devido a peculiaridades na estrutura do instalador padrão da Apple, você deve “concordar” com a licença do software para concluir a instalação. Como o Python é de código aberto, você está realmente “concordando” que a licença está concedendo a você direitos adicionais, em vez de retirá-los.

    Clique no botão Agree para continuar.

  6. [Instalador Python: tela de instalação padrão]

    A próxima tela permite que você altere o local de instalação. Você deve instalar o Python em sua unidade de inicialização, mas devido às limitações do instalador, ele não impõe isso. Na verdade, nunca precisei alterar o local de instalação.

    Nessa tela, você também pode personalizar a instalação para excluir determinados recursos. Se você quiser fazer isso, clique no botão Customize; caso contrário, clique no botão Install.

  7. [Instalador Python: tela de instalação personalizada]

    Se você escolher uma instalação personalizada, o instalador apresentará a seguinte lista de recursos:

    • Python Framework Esta é a essência do Python, e está selecionada e desativada porque deve ser instalada.
    • Os aplicativos GUI incluem o IDLE, o shell gráfico do Python que você usará ao longo deste livro. Eu recomendo fortemente manter esta opção selecionada.
    • As ferramentas de linha de comando do UNIX incluem o aplicativo de linha de comando python3. Eu recomendo fortemente manter essa opção também.
    • A documentação do Python contém muitas das informações sobre docs.python.org. Recomendado se você estiver usando uma conexão discada ou tiver acesso limitado à Internet.
    • O atualizador de perfil de shell controla se deve atualizar seu perfil de shell (usado em Terminal.app) para garantir que esta versão do Python esteja no caminho de pesquisa de seu shell. Você provavelmente não precisa mudar isso.
    • Sistema de correção Python não deve ser alterado. (Diz ao seu Mac para usar Python 3 como o Python padrão para todos os scripts, incluindo scripts de sistema integrados da Apple. Isso seria muito ruim, já que a maioria desses scripts são escritos para Python 2 e não funcionariam corretamente em Python 3.)

    Clique no botão Install para continuar.

  8. [Instalador Python: caixa de diálogo para inserir a senha administrativa]

    Como ele instala frameworks e binários em todo o sistema /usr/local/bin/, o instalador solicitará uma senha administrativa. Não há como instalar o Mac Python sem privilégios de administrador.

    Clique no botão OK para iniciar a instalação.

  9. [Instalador Python: medidor de progresso]

    O instalador exibirá um medidor de progresso enquanto instala os recursos que você selecionou.

  10. [Instalador Python: instalação bem-sucedida]

    Assumindo que tudo correu bem, o instalador apresentará uma grande marca de verificação verde para informar que a instalação foi concluída com êxito.

    Clique no botão Close para sair do instalador.

  11. [conteúdo da pasta / Applications / Python 3.1 /]

    Supondo que você não alterou o local de instalação, você pode encontrar os arquivos recém-instalados na pasta Python 3.1 dentro da sua pasta /Applications. A peça mais importante é o IDLE, o shell gráfico do Python.

    Clique duas vezes em IDLE para iniciar o Python Shell.

  12. [Mac Python Shell, um shell gráfico interativo para Python]

    O Python Shell é onde você passará a maior parte do tempo explorando o Python. Os exemplos ao longo deste livro presumirão que você pode encontrar seu caminho no Python Shell.

[Pule para o uso do Python Shell]

Instalando no Ubuntu Linux

As distribuições modernas do Linux são apoiadas por vastos repositórios de aplicativos pré-compilados, prontos para instalação. Os detalhes exatos variam de acordo com a distribuição. No Ubuntu Linux, a maneira mais fácil de instalar o Python 3 é por meio do aplicativo Add/Remove em seu menu Applications.

  1. [Adicionar / Remover: aplicativos mantidos pela Canonical]

    Ao iniciar o aplicativo Add/Remove pela primeira vez, ele mostrará uma lista de aplicativos pré-selecionados em diferentes categorias. Alguns já estão instalados; a maioria não. Como o repositório contém mais de 10.000 aplicativos, existem diferentes filtros que você pode aplicar para ver pequenas partes do repositório. O filtro padrão é “aplicativos mantidos pela Canonical”, que é um pequeno subconjunto do número total de aplicativos oficialmente suportados pela Canonical, a empresa que cria e mantém o Ubuntu Linux.

  2. [Adicionar / Remover: todos os aplicativos de código aberto]

    Python 3 não é mantido pela Canonical, então a primeira etapa é abrir este menu de filtro e selecionar “Todos os aplicativos de código aberto”.

  3. [Adicionar / Remover: procure Python 3]

    Depois de ampliar o filtro para incluir todos os aplicativos de código aberto, use a caixa Pesquisar imediatamente após o menu de filtro para pesquisar Python 3.

  4. [Adicionar / Remover: selecione o pacote Python 3.0]

    Agora, a lista de aplicativos se reduz a apenas aqueles correspondentes Python 3. Você vai verificar dois pacotes. O primeiro é Python (v3.0). Ele contém o próprio interpretador Python.

  5. [Adicionar / Remover: selecione IDLE para o pacote Python 3.0]

    O segundo pacote que você quer é imediatamente acima: IDLE (using Python-3.0). Este é um Python Shell gráfico que você usará ao longo deste livro.

    Depois de verificar esses dois pacotes, clique no botão Apply Changes para continuar.

  6. [Adicionar / Remover: aplicar alterações]

    O gerenciador de pacotes solicitará que você confirme se deseja adicionar IDLE (using Python-3.0)e Python (v3.0).

    Clique no botão Apply para continuar.

  7. [Adicionar / Remover: medidor de progresso do download]

    O gerenciador de pacotes mostrará um medidor de progresso enquanto baixa os pacotes necessários do repositório de Internet da Canonical.

  8. [Adicionar / Remover: medidor de progresso da instalação]

    Assim que os pacotes forem baixados, o gerenciador de pacotes começará a instalá-los automaticamente.

  9. [Adicionar / Remover: novos aplicativos foram instalados]

    Se tudo correr bem, o gerenciador de pacotes irá confirmar que ambos os pacotes foram instalados com sucesso. A partir daqui, você pode clicar duas vezes em IDLE para iniciar o Python Shell ou clicar no botão Close para sair do gerenciador de pacotes.

    Você sempre pode reiniciar o Python Shell acessando o menu Applications, o submenu Programming e selecionando IDLE.

  10. [Linux Python Shell, um shell gráfico interativo para Python]

    O Python Shell é onde você passará a maior parte do tempo explorando o Python. Os exemplos ao longo deste livro presumirão que você pode encontrar seu caminho no Python Shell.

[Pule para o uso do Python Shell]

Instalando em outras plataformas

Python 3 está disponível em várias plataformas diferentes. Em particular, está disponível em praticamente todas as distribuições baseadas em Linux, BSD e Solaris. Por exemplo, RedHat Linux usa o gerenciador de pacotes yum. FreeBSD tem suas portas e pacotes de coleta, SUSE tem zypper, e Solaris tem pkgadd. Uma rápida pesquisa na web por Python 3 + seu sistema operacional deve informar se um pacote Python 3 está disponível e, se estiver, como instalá-lo.

Usando o Python Shell

O Python Shell é onde você pode explorar a sintaxe do Python, obter ajuda interativa sobre comandos e depurar programas curtos. O Python Shell gráfico (denominado IDLE) também contém um editor de texto decente que suporta a coloração da sintaxe Python e se integra ao Python Shell. Se você ainda não tem um editor de texto favorito, experimente o IDLE.

Primeiras coisas primeiro. O próprio Python Shell é um playground interativo incrível. Ao longo deste livro, você verá exemplos como este:

>>> 1 + 1
2

Os três colchetes angulares, >>>, denotam o shell Python. Não digite essa parte. Isso é apenas para informá-lo de que este exemplo deve ser seguido no Python Shell.

1 + 1 é a parte que você digita. Você pode digitar qualquer expressão ou comando Python válido no Python Shell. Não seja tímido; não vai morder! O pior que vai acontecer é que você receberá uma mensagem de erro. Os comandos são executados imediatamente (assim que você pressiona ENTER); as expressões são avaliadas imediatamente e o Python Shell exibe o resultado.

2 é o resultado da avaliação desta expressão. Na verdade, é uma expressão Python válida. O resultado, claro, é 2.

Vamos tentar outro.

>>> print('Hello world!')
Hello world!

Muito simples, não? Mas há muito mais que você pode fazer no shell Python. Se você ficar preso - você não consegue se lembrar de um comando ou dos argumentos apropriados para passar uma determinada função - você pode obter ajuda interativa no Python Shell. Basta digitar help e pressionar ENTER.

>>> help
Type help() for interactive help, or help(object) for help about object.

Existem dois modos de ajuda. Você pode obter ajuda sobre um único objeto, que apenas imprime a documentação e retorna ao prompt do Python Shell. Você também pode entrar no modo de ajuda, onde ao invés de avaliar expressões Python, você apenas digita palavras-chave ou nomes de comandos e ele irá imprimir tudo o que sabe sobre aquele comando.

Para entrar no modo de ajuda interativa, digite help() e pressione ENTER.

>>> help()
Welcome to Python 3.0!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://docs.python.org/tutorial/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help>

Observe como o prompt muda de >>> para help>. Isso o lembra de que você está no modo de ajuda interativa. Agora você pode inserir qualquer palavra-chave, comando, nome de módulo, nome de função - quase tudo que Python entende - e ler a documentação sobre isso.

help> print                                                                 ①
Help on built-in function print in module builtins:

print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file: a file-like object (stream); defaults to the current sys.stdout.
    sep:  string inserted between values, default a space.
    end:  string appended after the last value, default a newline.

help> PapayaWhip                                                            ②
no Python documentation found for 'PapayaWhip'

help> quit                                                                  ③

You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)".  Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>>                                                                        ④
  1. Para obter a documentação da print()função, basta digitar printe pressionar ENTER. O modo de ajuda interativo exibirá algo semelhante a uma página de manual: o nome da função, uma breve sinopse, os argumentos da função e seus valores padrão e assim por diante. Se a documentação parecer obscura para você, não entre em pânico. Você aprenderá mais sobre todos esses conceitos nos próximos capítulos.

  2. Claro, o modo de ajuda interativo não sabe tudo. Se você digitar algo que não seja um comando, módulo, função ou outra palavra-chave embutida do Python, o modo de ajuda interativo apenas encolherá seus ombros virtuais.

  3. Para sair do modo de ajuda interativa, digite quit e pressione ENTER.

  4. O prompt muda de volta para >>> para sinalizar que você saiu do modo de ajuda interativo e retornou ao Python Shell.

IDLE, o Python Shell gráfico, também inclui um editor de texto compatível com Python.

Editores Python e IDEs

O IDLE não é o único jogo na cidade quando se trata de escrever programas em Python. Embora seja útil começar a aprender a linguagem nele, muitos desenvolvedores preferem outros editores de texto ou ambientes de desenvolvimento integrado (IDEs). Não os cobrirei aqui, mas a comunidade Python mantém uma lista de editores compatíveis com Python que cobre uma ampla gama de plataformas suportadas e licenças de software.

Você também pode querer verificar a lista de IDEs compatíveis com Python, embora poucos deles suportem Python 3 ainda. Um que o faz é o PyDev, um plug-in para Eclipse que transforma o Eclipse em uma IDE Python completa. Tanto o Eclipse quanto o PyDev são multiplataforma e de código aberto.

No front comercial, existe a IDE Komodo da ActiveState. Possui licenciamento por usuário, mas os alunos podem obter um desconto e uma versão de avaliação gratuita por tempo limitado está disponível.

Eu tenho programado em Python por nove anos, e edito meus programas em Python no GNU Emacs e os depuro no Python Shell de linha de comando. Não há maneira certa ou errada de desenvolver em Python. Encontre uma maneira que funcione para você!

Esse artigo é uma tradução de um capítulo do livro "Dive Into Python 3" escrito por Mark Pilgrim. Você pode ler o livro desde o início em português clicando aqui.

Traduzido por Acervo Lima. O original pode ser acessado aqui.

Licença

O que há de novo em “Dive Into Python 3”

Não é aqui que entramos?
- Pink Floyd, The Wall

também conhecido como “o nível negativo”

Você já é um programador Python? Você leu o “Dive Into Python” original? Você comprou no papel? (Em caso afirmativo, obrigado!) Você está pronto para mergulhar no Python 3? … Se sim, continue lendo. (Se nada disso for verdade, seria melhor começar do início).

Python 3 vem com um script chamado 2to3. Aprenda. Adore. Use-o. Portar código para Python 3 com 2to3 é uma referência de todas as coisas que a ferramenta 2to3 pode consertar automaticamente. Uma vez que muitas dessas coisas são mudanças da sintaxe, é um bom ponto de partida para aprender sobre um monte de mudanças de sintaxe em Python 3. (print agora é uma função, `x` não funciona, & c.).

Estudo de caso: Portar chardet para Python 3 documenta meu esforço (finalmente bem-sucedido) para portar uma biblioteca não trivial de Python 2 para Python 3. Isso pode ajudá-lo; pode não ser. Há uma curva de aprendizado bastante íngreme, já que você precisa entender a biblioteca primeiro, para que possa entender por que ela quebrou e como eu consertei. Muitas das rupturas giram em torno das strings. Falando nisso…

Strings. Uau. Onde começar. Python 2 tinha “strings” e “strings Unicode”. Python 3 tem “bytes” e “strings”. Ou seja, todas as strings são agora strings Unicode e, se você quiser lidar com um pacote de bytes, use o novo tipo bytes. O Python 3 nunca converterá implicitamente entre strings e bytes, portanto, se você não tiver certeza de qual possui em um determinado momento, seu código quase certamente falhará. Leia o capítulo Strings para mais detalhes.

Bytes vs. strings surge repetidamente ao longo do livro.

  • Em Arquivos, você aprenderá a diferença entre ler arquivos nos modos “binário” e “texto”. Ler (e gravar!) Arquivos em modo de texto requer um parâmetro encoding. Alguns métodos de arquivo de texto contam caracteres, mas outros métodos contam bytes. Se o seu código assume que um caractere é igual a um byte, ele será interrompido em caracteres multibyte.
  • Em HTTP Web Services, o módulo httplib2 busca cabeçalhos e dados em HTTP. Os cabeçalhos HTTP são retornados como strings, mas o corpo HTTP é retornado como bytes.
  • Em Serializando objetos Python, você aprenderá por que o módulo pickle em Python 3 define um novo formato de dados que é incompatível com versões anteriores do Python 2. (Dica: é por causa de bytes e strings.) Além disso, Python 3 oferece suporte à serialização de objetos de e para JSON, que nem mesmo tem um tipo bytes. Vou te mostrar como contornar isso.
  • No estudo de caso: portar chardet para Python 3, é apenas uma confusão sangrenta de bytes e strings em todos os lugares.

Mesmo que você não se importe com o Unicode (ah, mas você se importará), você vai querer ler sobre a formatação de strings no Python 3, que é completamente diferente do Python 2.

Os iteradores estão por toda parte no Python 3 e eu os entendo muito melhor do que há cinco anos, quando escrevi “Dive Into Python”. Você precisa entendê-los também, porque muitas funções que costumavam retornar listas no Python 2 agora retornarão iteradores no Python 3. No mínimo, você deve ler a segunda metade do capítulo Iteradores e a segunda metade do capítulo Iteradores avançados.

Por solicitação popular, adicionei um apêndice sobre nomes de métodos especiais, que é parecido com o capítulo “Modelo de dados” da documentação do Python, mas com mais detalhes.

Quando eu estava escrevendo “Dive Into Python”, todas as bibliotecas XML disponíveis eram péssimas. Então Fredrik Lundh escreveu ElementTree, que não é nada. Os deuses do Python sabiamente incorporaram ElementTree à biblioteca padrão e agora ele forma a base para meu novo capítulo XML. As velhas maneiras de analisar XML ainda existem, mas você deve evitá-las, porque elas são uma merda!

Outra novidade em Python - não na linguagem, mas na comunidade - é o surgimento de repositórios de código como o Python Package Index (PyPI). Python vem com utilitários para empacotar seu código em formatos padrão e distribuir esses pacotes no PyPI. Leia Empacotamento de bibliotecas Python para obter detalhes.

Esse artigo é uma tradução de um capítulo do livro "Dive Into Python 3" escrito por Mark Pilgrim.

Traduzido por Acervo Lima. O original pode ser acessado aqui.

Licença