Desempacotamento e Empacotamento em Python
Desempacotamento
O desempacotamento (também chamado de desestruturação) refere-se à divisão de uma coleção (como tupla, lista, etc.) em valores separados.
Assim como muitas outras linguagens de programação, o Python oferece suporte à atribuição múltipla. Por exemplo:
x, y = 1, 2
print(x) # 1
print(y) # 2
Neste exemplo, os valores são atribuídos a duas variáveis de uma vez. A atribuição é feita com base na posição: a variável x
recebe o valor 1 e a variável y
recebe o valor 2.
Esse exemplo já representa uma forma de desestruturação ou desempacotamento. Os valores 1 e 2, na verdade, formam uma tupla, pois a presença de vírgulas entre os valores caracteriza uma tupla. Poderíamos também ter escrito assim:
x, y = (1, 2)
print(x) # 1
print(y) # 2
Em qualquer caso, trata-se de desestruturação, onde o primeiro elemento da tupla é atribuído à primeira variável, o segundo elemento à segunda variável, e assim por diante. A divisão ocorre com base na posição.
Da mesma forma, podemos desempacotar outras tuplas, por exemplo:
name, age, company = ("Tom", 38, "Google")
print(name) # Tom
print(age) # 38
print(company) # Google
Não estamos limitados apenas a tuplas, pois também podemos desempacotar outras coleções, como listas:
people = ["Tom", "Bob", "Sam"]
first, second, third = people
print(first) # Tom
print(second) # Bob
print(third) # Sam
Ao desempacotar um dicionário, as variáveis recebem as chaves do dicionário:
dictionary = {"red": "vermelho", "blue": "azul", "green": "verde"}
r, b, g = dictionary
print(r) # red
print(b) # blue
print(g) # green
# obtendo o valor por chave
print(dictionary[g]) # verde
Desestruturação em laços
Em laços for
, podemos desempacotar coleções em partes individuais:
people = [
("Tom", 38, "Google"),
("Bob", 42, "Microsoft"),
("Sam", 29, "JetBrains")
]
for name, age, company in people:
print(f"Name: {name}, Age: {age}, Company: {company}")
Neste caso, percorremos uma lista de tuplas people
, onde cada tupla contém três elementos. Em cada iteração, esses elementos são atribuídos às variáveis name
, age
e company
.
Outro exemplo é a função enumerate()
, que recebe uma coleção como parâmetro, cria uma tupla para cada elemento e retorna um conjunto de tuplas. Cada tupla contém o índice, que é incrementado a cada iteração:
people = ["Tom", "Bob", "Sam"]
for index, name in enumerate(people):
print(f"{index}.{name}")
# resultado:
# 0.Tom
# 1.Bob
# 2.Sam
Ignorando valores
Se um elemento da coleção não for necessário, uma boa prática é usar um sublinhado (_
) como nome da variável. Isso indica que o valor é ignorado e não será usado posteriormente.
person = ("Tom", 38, "Google")
name, _, company = person
print(name) # Tom
print(company) # Google
Aqui, o segundo elemento da tupla é ignorado. Contudo, _
é um nome de variável válido, assim como name
e company
:
name, _, company = person
print(_) # 38
Empacotamento de valores e operador *
O operador *
é usado para empacotar valores em uma coleção. Por exemplo:
num1 = 1
num2 = 2
num3 = 3
*numbers, = num1, num2, num3
print(numbers) # [1, 2, 3]
Aqui, empacotamos os valores da tupla (num1, num2, num3)
em uma lista numbers. Para criar uma lista, colocamos uma vírgula após numbers
.
O empacotamento é útil para reunir os valores restantes após a atribuição dos resultados de uma desestruturação. Por exemplo:
head, *tail = [1, 2, 3, 4, 5]
print(head) # 1
print(tail) # [2, 3, 4, 5]
Neste caso, head recebe o primeiro elemento da lista e tail
recebe o restante dos elementos.
Podemos obter todos os elementos, exceto o último:
*head, tail = [1, 2, 3, 4, 5]
print(head) # [1, 2, 3, 4]
print(tail) # 5
Ou elementos do meio, exceto o primeiro e o último:
head, *middle, tail = [1, 2, 3, 4, 5]
print(head) # 1
print(middle) # [2, 3, 4]
print(tail) # 5
Ou todos os elementos, exceto os dois primeiros:
first, second, *other = [1, 2, 3, 4, 5]
print(first) # 1
print(second) # 2
print(other) # [3, 4, 5]
Com isso, podemos obter diferentes combinações de elementos em uma coleção. Isso se aplica não apenas a listas, mas também a tuplas, dicionários e outras coleções.
Um exemplo interessante é obter apenas o primeiro, terceiro e último elementos, ignorando os demais:
first, _, third, *_, last = [1, 2, 3, 4, 5, 6, 7, 8]
print(first) # 1
print(third) # 3
print(last) # 8
Também podemos obter as chaves de um dicionário:
red, *other, green = {"red": "vermelho", "blue": "azul", "yellow": "amarelo", "green": "verde"}
print(red) # red
print(green) # green
print(other) # ['blue', 'yellow']
Desempacotamento com operadores * e **
Os operadores *
e **
podem ser usados para desempacotar valores. O operador *
é utilizado para desempacotar tuplas, listas, strings e conjuntos, enquanto **
é usado para desempacotar dicionários. Isso é particularmente útil ao criar novas coleções a partir de outras. Por exemplo, desempacotamento de tuplas e listas:
nums1 = [1, 2, 3]
nums2 = (4, 5, 6)
# desempacotando a lista nums1 e a tupla nums2
nums3 = [*nums1, *nums2]
print(nums3) # [1, 2, 3, 4, 5, 6]
Aqui, desempacotamos os valores da lista nums1
e da tupla nums2
e os inserimos na lista nums3
.
O mesmo princípio se aplica a dicionários, usando o operador **
:
dictionary1 = {"red": "vermelho", "blue": "azul"}
dictionary2 = {"green": "verde", "yellow": "amarelo"}
# desempacotando dicionários
dictionary3 = {**dictionary1, **dictionary2}
print(dictionary3) # {'red': 'vermelho', 'blue': 'azul', 'green': 'verde', 'yellow': 'amarelo'}
Documentação oficial