Entenda o desempacotamento do Python
Um dos exercícios mais comuns nas aulas básicas de programação é sem dúvida
alguma o de trocar os valores das variáveis a
e b
.
// Codigo classico em linguagem c
int main(){
int a = 5, b = 7;
int tmp = a;
a = b;
b = tmp;
}
Mas se a linguagem for Python, existe uma outra maneira:
a = 5
b = 7
a, b = b, a
Ok até agora não tivemos muitas novidades, provavelmente você já viu isso em algum lugar. Mas neste post eu vou apresentar mais algumas possibilidades deste desempacotamento do Python!
Desempacotamento com Python⌗
Algo que eu faço muito resolvendo exercícios do
URI é ler a linha dar um split
na linha
e converter todos os elementos para um tipo especifico, geralmente int
.
Claro que podemos fazer isso de várias formas, por exemplo:
linha = input().split()
a = int(linha[0])
b = int(linha[1])
c = int(linha[2])
d = int(linha[3])
Esse exemplo funcionaria, mas seria extremamente lento de se escrever isso se tivermos várias variáveis diferentes na linha, então hoje eu uso muito, mas muito mesmo essa solução com list-comprehensions:
a, b, c, d = [int(x) for x in input().split()]
De cinco linhas para uma até que nos livramos de uma boa parte de código repetitivo!
Melhorando a legibilidade do código⌗
Agora vamos a um exemplo menos bobinho, e também com menos cara de exercício de programação, sem unpacking:
curso = get_curso_by_id(2)
print("Nome:", curso[1])
print("Coordenador:", curso[3])
print("Data de Inicio:", curso[4])
print("Descrição:", curso[2])
A função get_curso_by_id()
retorna uma tupla com: id, nome, descrição,
coordenador, data de inicio. Referenciar estes campos por seu índices é
uma solução feia que permite muitos erros. Então vamos deixar este código mais
legível com desempacotamento:
id_curso, nome, desc, coordenador, dt_inicio = get_curso_by_id(2)
print("Nome:", nome)
print("Coordenador:", coordenador)
print("Data de Inicio:", dt_inicio)
print("Descrição:", desc)
Muito mais legível!
Agora vamos dizer que a data retorna também uma tupla com anos, mês e dia. Para separar esses valores também nos poderíamos fazer o seguinte:
id_curso, nome, desc, coordenador, (ano, mes, dia) = get_curso_by_id(2)
print("Nome:", nome)
print("Coordenador:", coordenador)
print("Data de Inicio:", "{}/{}/{}".format(dia, mes, ano))
print("Descrição:", desc)
Ignorando valores⌗
Agora vamos dizer que você precisa apenas do nome do curso e do coordenador,
o Python não possui nenhuma sintaxe específica pra isso, mas você pode
simplesmente atribuir esses campos para uma variável aleatória, como _
:
_, nome, _, coordenador, _ = get_curso_by_id(2)
Desempacotando valores de iteráveis de tamanho variável⌗
Tudo isso e muito bonito mas é no caso de iteráveis que eu não sei exatamente o
tamanho? É agora que entram as *
no Python, mas acalme-se meu jovem
traumatizado pelos ponteiros de C essa estrelinha não tem nenhuma relação com
eles.
>>> aluno
('João', 'joao@bol.com.br', '(11) 93233-32323', '(11) 93233-3863', '(11) 98603-32323')
>>> nome, email, *telefones
>>> nome
'João'
>>> email
'joao@bol.com.br'
>>> telefones
['(11) 93233-32323', '(11) 93233-3863', '(11) 98603-32323']
Em detalhes: nome
e email
receberam os dois primeiros elementos, e
telefones
recebeu todo o resto.
E claro que as ’estrelinhas’ não servem só pra desempacotar os últimos elementos: elas podem estar no meio, no incio e no fim da expressões de desempacotamento.
A única exigência e que exista apenas um ‘valor estrelado’ na expressão:
>>> l
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>> a, *b, c, *d = l
File "<stdin>", line 1
SyntaxError: two starred expressions in assignment
>>>
Passando um iterável ou dicionário como argumentos de uma função⌗
Essa talvez você já tenha visto em algum lugar:
>>> def a(*args, **kwargs):
... print(args)
... print(kwargs)
...
>>> a(1, 2, 'a', 'b', z=9, x=8)
(1, 2, 'a', 'b')
{'z': 9, 'x': 8}
>>>
E aí, o que achou dessa forma de desempacotar dados com o Python?