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

0 comentários:

Postar um comentário