Tuplas e conjuntos

Você conhece listas. Python tem mais dois tipos de coleção que resolvem problemas que listas não conseguem. Tuplas guardam um grupo fixo de valores que nunca vai mudar. Conjuntos guardam apenas valores únicos e deixam você verificar pertencimento instantaneamente, não importa o tamanho da coleção.
Tuplas
Uma tupla é um grupo ordenado de valores que não pode ser mudado após criar. Parênteses definem uma tupla, mas são opcionais. A vírgula é o que realmente faz uma tupla. Uma tupla de um único item requer uma vírgula no final.
point = (10, 20)
rgb = (255, 128, 0)
dimensions = (1920, 1080)
single = (42,) # vírgula no final obrigatória para tupla de um item
also_tuple = 42, 99 # parênteses são opcionais; a vírgula faz uma tuplaAcesso por índice funciona exatamente como uma lista. Tentar mudar um item levanta TypeError:
point = (10, 20)
point[0] # 10
point[1] # 20
point[-1] # 20
point[0] = 99 # TypeError: 'tuple' object does not support item assignment(42,) precisa daquela vírgula solitária no final. Tente reatribuir um item e você recebe um TypeError, e esse sentimento de bloqueado é exatamente por que você escolheria uma tupla. Quando usar uma tupla
Use uma tupla quando você tem um pequeno grupo de valores relacionados que pertencem juntos e não vão mudar. Coordenadas (x, y), uma cor (r, g, b), um par nome-pontuação ("Maria", 87). A estrutura fixa sinaliza a qualquer um lendo o código que este grupo é tratado como uma unidade única.
(r, g, b), um par nome-e-pontuação. Porque tuplas são hashable, você pode até usar uma como chave de dicionário. Uma lista não consegue fazer isso, o que pega as pessoas da primeira vez que tentam. locations = {}
locations[(40, -74)] = "São Paulo" # tupla como chave de dicionário, funciona
locations[[40, -74]] = "São Paulo" # lista como chave de dicionário, TypeErrorDesempacotamento
Desempacotamento puxa valores para fora de uma tupla e atribui cada um a seu próprio nome em uma única linha. O número de nomes deve combinar com o número de valores. Use * para capturar quaisquer itens restantes em uma lista.
x, y = point. O número de nomes tem que combinar com o número de valores, a menos que você adicione um *rest para colher o que sobrar. Fez clique para mim o dia em que parei de escrever point[0] e point[1] em todo lugar. point = (10, 20)
x, y = point
print(x) # 10
print(y) # 20
first, *rest = [1, 2, 3, 4, 5]
# first = 1, rest = [2, 3, 4, 5]
head, *middle, tail = [1, 2, 3, 4, 5]
# head = 1, middle = [2, 3, 4], tail = 5Tuplas nomeadas
Uma tupla nomeada é uma tupla onde cada posição tem um nome. Em vez de lembrar que point[0] é a coordenada x, você escreve point.x. Os valores ainda são imutáveis; você recebe nomes de atributo legíveis em vez de posições numéricas.
point.x em vez de lembrar que point[0] é o x. Ainda é totalmente imutável e age como uma tupla normal em qualquer outro aspecto. Seu eu futuro lendo o código vai agradecer pelos nomes. namedtuple vive na biblioteca padrão, então precisa de uma importação primeiro: from collections import namedtuple. Importações recebem tratamento completo no capítulo Módulos.
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
Player = namedtuple("Player", ["name", "score", "level"])
p = Point(10, 20)
p.x # 10
p.y # 20
alice = Player("Maria", 87, 5)
alice.name # "Maria"
alice.score # 87Conjuntos
Um conjunto é uma coleção de valores únicos sem ordem garantida. Adicionar o mesmo valor duas vezes não faz nada: um conjunto mantém apenas uma cópia de cada item. Use chaves para um conjunto com itens, ou set() para criar um conjunto vazio.
set() para um vazio, porque {} é secretamente um dicionário vazio. Essa última parte pega quase todo mundo. tags = {"python", "iniciante", "tutorial"}
numbers = {1, 2, 3, 4, 5}
empty = set() # NÃO {} (isso é um dicionário vazio)Adicionar o mesmo valor duas vezes não muda o conjunto:
tags.add("python") # tags não muda, "python" já está neleQuando usar um conjunto
Conjuntos são a ferramenta certa para três coisas: remover duplicatas de uma lista, verificar rapidamente se algo está em uma grande coleção e comparar dois grupos para encontrar o que eles compartilham ou diferem.
# Remover duplicatas de uma lista
raw = ["gato", "cachorro", "gato", "pássaro", "cachorro", "gato"]
unique = list(set(raw)) # ["gato", "cachorro", "pássaro"] (ordem não garantida)# Verificação rápida de pertencimento
valid_codes = {"USD", "EUR", "GBP", "JPY"}
code = "EUR"
if code in valid_codes: # busca instantânea, mesmo com milhares de códigos
print("Válido")Operações de conjunto
Conjuntos suportam as mesmas operações que você aprendeu em matemática: união (tudo em qualquer conjunto), interseção (apenas o que ambos os conjuntos compartilham) e diferença (o que um tem que o outro não tem). Python usa símbolos de operador para esses, e cada um tem um equivalente de método.
| é união (em qualquer um), & é interseção (em ambos), - é diferença (em um mas não no outro) e ^ é diferença simétrica (em um mas não em ambos). Cada uma também tem um método escrito como .union() se você preferir palavras a símbolos. a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
a | b # {1, 2, 3, 4, 5, 6} (união: tudo em qualquer um)
a & b # {3, 4} (interseção: apenas em ambos)
a - b # {1, 2} (diferença: em a mas não em b)
b - a # {5, 6} (diferença do outro lado)
a ^ b # {1, 2, 5, 6} (diferença simétrica: em um mas não em ambos)Esses também têm formas de método: .union(), .intersection(), .difference(), .symmetric_difference().
Modificando conjuntos
Conjuntos são mutáveis. .add() adiciona um item. .update() adiciona vários de uma vez de qualquer lista ou outro iterável. .remove() deleta um item mas levanta um erro se não estiver lá. .discard() deleta silenciosamente se o item existe e faz nada se não existe.
.add() coloca um item, .update() adiciona um lote inteiro de uma lista ou outro iterável. O par para manter reto é remoção: .remove() erra se o item não estiver lá, enquanto .discard() encolhe os ombros e segue em frente. Quando você não tem certeza se está no conjunto, .discard() lhe poupa um erro aleatório. tags = {"python", "iniciante"}
tags.add("tutorial") # adicionar um item
tags.update(["web", "api"]) # adicionar múltiplos itens de qualquer iterável
tags.remove("iniciante") # remover, levanta KeyError se não encontrado
tags.discard("faltando") # remover, nenhum erro se não encontrado
tags.pop() # remover e retornar um item arbitrário
tags.clear() # remover tudoUse .discard() quando você não tem certeza se o item existe.
Conjuntos congelados
Um conjunto congelado é um conjunto que você não consegue modificar após criação. A razão principal para usar um: conjuntos congelados são hashable, então podem ser usados como chaves de dicionário ou armazenados dentro de outros conjuntos.
valid_statuses = frozenset({"ativo", "pausado", "deletado"})
valid_statuses.add("arquivado") # AttributeError, frozenset é imutávelEscolhendo a coleção certa
Quatro tipos, cada um com um papel claro. Pergunte o que você precisa fazer com os dados e a escolha certa geralmente segue.
| list | tuple | set | dict | |
|---|---|---|---|---|
| Ordenada | Sim | Sim | Não | Sim (ordem de inserção) |
| Mutável | Sim | Não | Sim | Sim |
| Duplicatas | Sim | Sim | Não | Não (chaves) |
| Acesso por | Índice | Índice | n/a | Chave |
| Use quando | Sequência ordenada, mutável | Registro fixo | Valores únicos, pertencimento rápido | Busca chave-valor |
Uma regra de decisão rápida:
- Precisa procurar algo por nome? → dict
- Precisa de uma coleção ordenada que vai modificar? → list
- Tem um grupo fixo de valores relacionados? → tuple
- Precisa de valores únicos ou testes rápidos de pertencimento? → set
Na prática
Usando tuplas para armazenar registros fixos e um conjunto para rastrear valores únicos:
home = (-15.7975, -47.8919) # latitude, longitude
office = (-15.7864, -47.8778)
home_lat, home_lon = home
print(f"Casa: {home_lat}, {home_lon}")
# Rastrear visitantes únicos com um conjunto
visitors = set()
visitors.add("maria")
visitors.add("joão")
visitors.add("maria") # já está no conjunto, silenciosamente ignorado
visitors.add("carolina")
print(f"Visitantes únicos: {len(visitors)}")
print(f"maria visitou: {'maria' in visitors}")
print(f"pedro visitou: {'pedro' in visitors}")
