Curso de Python / Tuplas e desempacotamento de valores

Uma tupla é uma sequência ordenada cujas referências aos itens não podem ser substituídas. Ela é útil para registros curtos e para desempacotar vários valores, mas os objetos mutáveis guardados dentro dela ainda podem mudar.

Crie tuplas e delimite a imutabilidade

A vírgula é o elemento decisivo para criar uma tupla não vazia; os parênteses tornam o agrupamento mais claro. Uma tupla de um item precisa da vírgula final, como (3500,). Já (3500) é apenas uma expressão inteira entre parênteses. A tupla vazia é escrita como ().

single = (3500,)
record = ("lunch", 8000)
print(type(single).__name__)
print(record[0])

Esse pequeno exemplo mostra tuple na primeira linha de saída e lunch na segunda. Assim como uma lista, uma tupla permite ler elementos por índice, começando em zero. A diferença é que uma atribuição a uma posição, como record[0] = "dinner", provoca TypeError.

Imutabilidade da tupla não significa imutabilidade de todo o conteúdo. Com pair = ([1], 2), a operação pair[0] = [] falha, mas pair[0].append(3) modifica a lista interna e deixa pair com o valor ([1, 3], 2). A referência naquela posição continua apontando para a mesma lista. A seção oficial sobre tuplas e sequências apresenta essa distinção.

Execute o desempacotamento de uma sequência

Salve o programa completo abaixo em UTF-8 como tuples.py, na pasta do projeto. Execute python tuples.py no ambiente selecionado. No macOS ou Ubuntu, fora de um ambiente virtual, use python3 se esse for o nome do interpretador. Não são necessários pacotes nem arquivos de dados.

record = ("lunch", 8000, "food")
name, amount, category = record
print(name, amount, category)
first, *rest = [3500, 8000, 2500]
print(first, rest)
a, b = 1, 2
a, b = b, a
print(a, b)

A saída esperada é:

lunch 8000 food
3500 [8000, 2500]
2 1

A atribuição a name, amount e category separa os três campos da tupla conforme sua posição. Na segunda parte, first recebe 3500 e rest recebe uma lista com os elementos restantes. A última atribuição troca os valores de a e b: as expressões à direita são avaliadas antes de os nomes à esquerda receberem os novos valores.

Confira a quantidade e o significado dos valores

Sem um alvo com asterisco, a quantidade de itens deve corresponder à quantidade de nomes. Dois itens para três nomes, ou quatro itens para três nomes, provocam ValueError. A correspondência de quantidade não valida o significado: inverter os campos do registro pode atribuir um valor ao nome errado sem produzir uma exceção.

Um alvo como *rest recebe os elementos restantes em uma lista, que pode estar vazia. Em um mesmo padrão de desempacotamento, somente um alvo pode ter o asterisco. Por exemplo, first, *rest = [3500] resulta em first igual a 3500 e rest igual a []; uma lista vazia ainda falha porque falta o elemento obrigatório para first. A referência de atribuições descreve essas regras.

Desempacotar um dicionário diretamente usa suas chaves, não seus valores. Para percorrer pares de chave e valor, use items() e desempacote cada par. Quando os registros vêm de um arquivo ou de uma rede, confira a quantidade e a ordem dos campos antes de assumir que toda linha tem o mesmo formato.

Escolha entre lista, tupla e campos nomeados

Necessidade Estrutura adequada
Sequência de valores que recebe novos itens Lista
Pequeno registro com posições bem definidas Tupla
Registro em que os nomes dos campos são importantes Dicionário ou dataclass

A aula sobre alterações e cópias de listas ajuda a comparar os objetos mutáveis. Uma tupla pode servir como chave de dicionário somente se todos os seus elementos forem hashable. Esse termo descreve objetos com hash estável e comportamento de igualdade compatível, requisitos usados na identificação das chaves. Uma tupla que contém uma lista não atende a esse requisito; confira a definição de hashable no glossário Python.

  1. No programa completo, retire somente "food" da tupla record. A atribuição a três nomes deve falhar com ValueError.
  2. Para trabalhar com o registro de dois campos, mude a atribuição para name, amount = record e a primeira exibição para print(name, amount). Ajustar apenas os nomes da atribuição deixaria uma referência a category inexistente na linha seguinte. Com as duas alterações, a primeira linha deve ser lunch 8000, e as duas linhas seguintes permanecem iguais.
  3. Restaure o campo "food", a atribuição a três nomes e a exibição de category. Confira novamente a saída original.

Quando as posições de um registro ficam difíceis de lembrar, prefira campos nomeados. A estrutura deve tornar explícito o significado dos dados, além de permitir que o programa faça a atribuição sem erro.