Laços aninhados em Python: padrões, desempenho e quando evitar
Este tutorial foi traduzido do original em inglês.Read in EnglishLeer en españolЧитать на русскомอ่านภาษาไทยAvisar sobre um erro de tradução
Pense em uma planilha. Ela tem linhas e colunas. Para ler cada célula, você passa por cada linha e, em cada linha, passa por cada coluna. São dois laços, um dentro do outro. Isso é um laço aninhado.
Os laços aninhados aparecem em todo lugar na programação: para desenhar padrões em grade, procurar em tabelas, gerar combinações e processar imagens pixel por pixel. Eles são poderosos, mas também podem ser surpreendentemente lentos se você não tomar cuidado.
Neste tutorial, você vai aprender como os laços aninhados funcionam, ver exemplos práticos com grades e combinações, entender por que eles podem ser lentos e descobrir quando usar alternativas.
Como funcionam os laços aninhados em Python?
Um laço aninhado é um laço dentro de outro laço. O laço externo começa primeiro. A cada iteração do laço externo, o laço interno roda inteiro, do começo ao fim.
(1,1) (1,2) (1,3) (2,1) (2,2) (2,3) (3,1) (3,2) (3,3)
Aqui está a ideia principal: se o laço externo roda n vezes e o laço interno roda m vezes, o código dentro do laço interno é executado n x m vezes no total. Três linhas e três colunas significam que o print() interno roda 9 vezes.
Total iterations: 15
Trabalhando com dados em 2D (grades e tabelas)
O uso mais prático dos laços aninhados é trabalhar com dados bidimensionais. Uma lista de listas em Python representa uma grade, uma tabela ou uma matriz. O laço externo percorre as linhas, e o laço interno percorre as colunas de cada linha.
1 2 3 4 5 6 7 8 9
Às vezes você precisa do índice da linha e da coluna, não só dos valores. Use enumerate() para isso.
X found at row 0, col 0 X found at row 0, col 2 X found at row 1, col 1 X found at row 2, col 2
Aqui vai um exemplo prático: montar uma tabuada.
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 5 10 15 20 25
Gerando combinações com laços aninhados
Os laços aninhados são perfeitos para gerar todas as combinações de itens de dois (ou mais) grupos. O laço externo escolhe do primeiro grupo, e o laço interno escolhe do segundo.
All t-shirt options: red - S red - M red - L blue - S blue - M blue - L
Com 2 cores e 3 tamanhos, você obtém 6 combinações. Cada cor é combinada com cada tamanho. Isso se chama produto cartesiano das duas listas.
Pairs that sum to 10: 1 + 9 = 10 3 + 7 = 10
Desenhando padrões com laços aninhados
Desenhar padrões é um exercício clássico para entender laços aninhados. Cada linha é controlada pelo laço externo, e o número de caracteres em cada linha é controlado pelo laço interno.
* ** *** **** *****
O segredo é que o intervalo do laço interno depende da variável do laço externo. Na linha 1, o laço interno roda uma vez. Na linha 2, duas vezes. Na linha 5, cinco vezes. É isso que cria o formato de escada.
***** **** *** ** *
Desempenho: por que os laços aninhados podem ser lentos
Um laço simples sobre 1.000 itens roda 1.000 vezes. Um laço aninhado sobre 1.000 itens roda 1.000 x 1.000 = 1.000.000 de vezes. Isso é um milhão de operações. Acrescente um terceiro nível de aninhamento e você chega a um bilhão. Os laços aninhados se multiplicam, e os números crescem rápido.
Os cientistas da computação descrevem isso com a notação Big O. Um laço simples é O(n): o tempo cresce de forma linear com o tamanho dos dados. Um laço aninhado é O(n²): o tempo cresce com o quadrado do tamanho dos dados. Dobre a entrada e o trabalho quadruplica.
Single loop: 0.0000 seconds Nested loop: 0.8120 seconds Nested is 8120x slower
Quando evitar laços aninhados
Nem todo problema que parece precisar de laços aninhados precisa de fato. Muitas vezes existe um caminho mais rápido usando conjuntos, dicionários ou funções embutidas.
nums = [3, 1, 4, 1, 5, 9]
has_dup = False
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] == nums[j]:
has_dup = True
print(has_dup) # Truenums = [3, 1, 4, 1, 5, 9]
has_dup = len(nums) != len(set(nums))
print(has_dup) # TrueA versão com conjunto não é só mais curta: ela é muito mais rápida. Para 10.000 itens, a versão com laço aninhado faz 50 milhões de comparações. A versão com conjunto faz cerca de 10.000 operações. Isso é 5.000 vezes mais rápido.
students = [
{'name': 'Alice', 'id': 101},
{'name': 'Bob', 'id': 102},
{'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]
for target_id in ids_to_find:
for s in students:
if s['id'] == target_id:
print(s['name'])students = [
{'name': 'Alice', 'id': 101},
{'name': 'Bob', 'id': 102},
{'name': 'Charlie', 'id': 103}
]
ids_to_find = [103, 101]
lookup = {s['id']: s['name'] for s in students}
for target_id in ids_to_find:
print(lookup[target_id])Exercícios práticos
Estes exercícios vão reforçar o seu entendimento de laços aninhados. Eles começam com padrões básicos e vão em direção a problemas do mundo real.
Exiba um retângulo de estrelas com 3 linhas e 5 colunas. Cada linha deve ter 5 estrelas, sem espaços entre elas.
Saída esperada:
*****
*****
*****Sem executar o código, preveja o que ele vai exibir. Conte o número total de linhas da saída. Depois execute para conferir.
Exiba um triângulo de números em que cada linha contém o número da linha repetido. O triângulo tem 4 linhas.
Saída esperada:
1
22
333
4444Uma grade de números já está pronta. Use laços aninhados para calcular e exibir a soma de todos os valores da grade.
Saída esperada:
45Dada uma lista de peças de cima e outra de peças de baixo, exiba todas as combinações de roupa possíveis e, no final, o total.
Saída esperada:
shirt + jeans
shirt + shorts
sweater + jeans
sweater + shorts
hoodie + jeans
hoodie + shorts
Total outfits: 6Este código deveria exibir uma grade de coordenadas 3x3, mas tem um bug. A saída deve mostrar uma linha de coordenadas por linha de texto, com x indo de 0 a 2 e y indo de 0 a 2.
Saída esperada:
(0,0) (0,1) (0,2)
(1,0) (1,1) (1,2)
(2,0) (2,1) (2,2)Encontre e corrija o bug.
Resumo: laços aninhados em Python
Veja o que você aprendeu sobre laços aninhados:
| Conceito | Ideia principal |
|---|---|
| Laço aninhado | Um laço dentro de outro laço |
| Total de iterações | Vezes do externo x vezes do interno |
| Dados em 2D | Laço externo = linhas, laço interno = colunas |
| Combinações | Combinar cada item do grupo A com cada item do grupo B |
| Desempenho | O(n²): dobre a entrada e o trabalho quadruplica |
| Alternativas | Conjuntos e dicionários muitas vezes substituem laços aninhados |
Regras práticas:
'*' * n) muitas vezes substitui laços internos em padrõesO que vem a seguir?
No próximo tutorial, Como ler as mensagens de erro do Python, você vai aprender a decifrar as mensagens de erro do Python, corrigir os bugs mais comuns e perder o medo dos tracebacks. Depurar é uma habilidade que facilita todo o resto.