Python Laços Aninhados
Dentro do bloco de um laço pode ir qualquer coisa: um print, um if… e também outro laço. Um laço dentro do outro se chama laço aninhado (como um ninho, um dentro do outro). É o que você usa quando o trabalho tem duas "dimensões": as fileiras e as cadeiras de um teatro, as linhas e as colunas de uma tabela, as tabuadas e os números de cada tabuada.
- Como se escreve um laço dentro do outro, e a regra de ouro: o de dentro dá a volta completa a cada volta do de fora.
- A contar quantas vezes o bloco de dentro roda.
- A montar a tabuada e uma grade de multiplicação.
- A desenhar com
*: retângulo, triângulo, triângulo invertido e pirâmide. - Que o
breaksó sai do laço de dentro, e como sair dos dois. - Os erros reais: o mesmo nome de variável nos dois laços, o
print()fora do lugar e oIndentationError.
Todos os programas desta aula rodaram no Python 3.14 da máquina da Ana (usuária ana, computador notebook), com python3 arquivo.py. Esta aula usa o for, o range() e o end do print (aula As Opções sep e end).
A ideia: o lanterninha do teatro
O teatro do bairro tem 3 fileiras (A, B e C), cada uma com 4 cadeiras. Antes do espetáculo, o lanterninha confere todas as cadeiras. Ele faz assim:
- Vai para a fileira A e confere as cadeiras 1, 2, 3 e 4.
- Só então passa para a fileira B e confere as cadeiras 1, 2, 3 e 4 de novo.
- Depois a fileira C: cadeiras 1, 2, 3 e 4.
São dois laços. O de fora anda pelas fileiras, devagar: só 3 voltas. O de dentro anda pelas cadeiras, depressa, e recomeça do 1 a cada fileira nova. No total, ele conferiu 3 × 4 = 12 cadeiras. É como os ponteiros de um relógio: o dos minutos dá a volta inteira para o das horas andar um passo.
1. O primeiro laço aninhado
for fileira in "ABC":
for cadeira in range(1, 5):
print(f"{fileira}{cadeira}", end=" ")
print()
$ python3 cadeiras.py A1 A2 A3 A4 B1 B2 B3 B4 C1 C2 C3 C4
- for fileira in "ABC":
- O laço de fora: percorre as letras A, B e C (3 voltas).
- for cadeira in range(1, 5):
- O laço de dentro, com 4 espaços: faz parte do bloco do de fora. Percorre 1, 2, 3 e 4, e começa tudo de novo a cada fileira.
- print(f"{fileira}{cadeira}", end=" ")
- O bloco do laço de dentro, com 8 espaços. Mostra a cadeira (A1, A2…) e, por causa do
end=" ", fica na mesma linha, com um espaço depois. Repare que ele usa as duas variáveis: a do de fora e a do de dentro. - print()
- Com 4 espaços: está no laço de fora, mas depois do de dentro. Roda uma vez por fileira, quando as 4 cadeiras já foram mostradas, e só pula a linha.
Seguindo as voltas, uma por uma
Para enxergar a ordem em que as coisas acontecem, este programa avisa quando cada volta do laço de fora começa e termina:
for fora in range(1, 3):
print(f"Começa a volta {fora} do laço de fora")
for dentro in range(1, 4):
print(f" fora = {fora}, dentro = {dentro}")
print(f"Termina a volta {fora} do laço de fora")
print("Acabou tudo.")
$ python3 voltas.py
Começa a volta 1 do laço de fora
fora = 1, dentro = 1
fora = 1, dentro = 2
fora = 1, dentro = 3
Termina a volta 1 do laço de fora
Começa a volta 2 do laço de fora
fora = 2, dentro = 1
fora = 2, dentro = 2
fora = 2, dentro = 3
Termina a volta 2 do laço de fora
Acabou tudo.
Enquanto o laço de dentro roda, a variável fora fica parada: vale 1 nas três primeiras linhas de dentro e 2 nas três seguintes. Já a dentro recomeça do 1 a cada volta de fora.
Multiplique: voltas do de fora × voltas do de dentro. Aqui, 2 × 3 = 6 linhas com fora = …, dentro = …. No teatro, 3 × 4 = 12 cadeiras. A conta cresce rápido: dois laços de 100 voltas fazem o bloco de dentro rodar 10000 vezes. Para o computador ainda é pouco, mas vale lembrar quando os números forem grandes.
2. A tabuada
O exemplo mais famoso de laço aninhado. O laço de fora escolhe qual tabuada; o de dentro passa pelos números de 1 a 10:
for numero in range(1, 4):
print(f"Tabuada do {numero}")
for vezes in range(1, 11):
print(f"{numero} x {vezes} = {numero * vezes}")
print()
$ python3 tabuada.py Tabuada do 1 1 x 1 = 1 1 x 2 = 2 1 x 3 = 3 1 x 4 = 4 1 x 5 = 5 1 x 6 = 6 1 x 7 = 7 1 x 8 = 8 1 x 9 = 9 1 x 10 = 10 Tabuada do 2 2 x 1 = 2 2 x 2 = 4 2 x 3 = 6 2 x 4 = 8 2 x 5 = 10 2 x 6 = 12 2 x 7 = 14 2 x 8 = 16 2 x 9 = 18 2 x 10 = 20 Tabuada do 3 3 x 1 = 3 3 x 2 = 6 3 x 3 = 9 3 x 4 = 12 3 x 5 = 15 3 x 6 = 18 3 x 7 = 21 3 x 8 = 24 3 x 9 = 27 3 x 10 = 30
O título Tabuada do … está no laço de fora, antes do de dentro: aparece uma vez por tabuada, em cima. O print() vazio está no laço de fora, depois do de dentro: deixa uma linha em branco entre uma tabuada e outra. Dentro do {…} da f-string pode ir uma conta: {numero * vezes}.
Missão: a Ana está estudando as tabuadas mais difíceis. Mude o programa para mostrar as tabuadas do 7, do 8 e do 9 (cada uma de 1 a 10).
for numero in range(1, 4):
print(f"Tabuada do {numero}")
for vezes in range(1, 11):
print(f"{numero} x {vezes} = {numero * vezes}")
print()
for numero in range(7, 10):
print(f"Tabuada do {numero}")
for vezes in range(1, 11):
print(f"{numero} x {vezes} = {numero * vezes}")
print()
A grade de multiplicação
Com o end="", o laço de dentro escreve uma linha inteira, e o de fora empilha as linhas. Sai uma tabela, como as do fundo do caderno:
for linha in range(1, 6):
for coluna in range(1, 6):
print(f"{linha * coluna:3}", end="")
print()
$ python3 grade.py 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
O :3 dentro das chaves manda o número ocupar 3 casas, completando com espaços à esquerda. É isso que deixa as colunas alinhadas, tanto para o 1 quanto para o 25. (Os detalhes dessa formatação estão em f-strings e em Formatação.)
3. Desenhando com asteriscos
Desenhar figuras com * é um treino clássico de laços aninhados: o laço de fora cuida das linhas; o de dentro, das estrelas de cada linha.
Retângulo: todas as linhas iguais
for linha in range(3):
for coluna in range(5):
print("*", end="")
print()
$ python3 retangulo.py ***** ***** *****
3 linhas, 5 estrelas em cada. O laço de dentro sempre dá 5 voltas, então todas as linhas ficam iguais.
Triângulo: o laço de dentro depende do de fora
Agora o pulo do gato. Se o número de voltas do laço de dentro usar a variável do de fora, cada linha fica de um tamanho:
for linha in range(1, 6):
for estrela in range(linha):
print("*", end="")
print()
$ python3 triangulo.py * ** *** **** *****
| Volta de fora | linha | O de dentro: range(linha) | Estrelas |
|---|---|---|---|
| 1ª | 1 | range(1): 1 volta | * |
| 2ª | 2 | range(2): 2 voltas | ** |
| 3ª | 3 | range(3): 3 voltas | *** |
| 4ª | 4 | range(4): 4 voltas | **** |
| 5ª | 5 | range(5): 5 voltas | ***** |
Triângulo invertido
Basta o laço de fora contar para trás (passo negativo, veja range()):
for linha in range(5, 0, -1):
for estrela in range(linha):
print("*", end="")
print()
$ python3 invertido.py ***** **** *** ** *
Experimente: troque o "*" por "#" ou por um número (print(linha, end="")), e o range(5, 0, -1) por range(8, 0, -2). Antes de rodar, tente imaginar o desenho.
for linha in range(5, 0, -1):
for estrela in range(linha):
print("*", end="")
print()
4. O break só sai do laço de dentro
O break (aula break e continue) sai do laço em que ele está, que é sempre o mais de dentro. O laço de fora continua como se nada tivesse acontecido. Este programa procura, para cada a de 1 a 6, um b de 1 a 6 com a × b = 12:
for a in range(1, 7):
for b in range(1, 7):
if a * b == 12:
print(f"{a} x {b} = 12")
break
$ python3 break_dentro.py 2 x 6 = 12 3 x 4 = 12 4 x 3 = 12 6 x 2 = 12
Cada break encerrou só a busca do b; o laço do a seguiu para o próximo número. Por isso apareceram quatro respostas, uma para cada a que tem par (o 1 e o 5 não têm nenhum b até 6 que dê 12).
E para parar tudo no primeiro que achar?
Um jeito é a variável achou, a "bandeira" que você viu em else nos Laços: o laço de dentro levanta a bandeira antes do break, e o de fora olha para ela logo depois:
achou = False
for a in range(1, 7):
for b in range(1, 7):
if a * b == 12:
print(f"Primeiro par: {a} x {b} = 12")
achou = True
break
if achou:
break
print("Busca encerrada.")
$ python3 break_tudo.py Primeiro par: 2 x 6 = 12 Busca encerrada.
São dois break: o de 12 espaços sai do laço do b; o de 8 espaços, logo abaixo do if achou:, sai do laço do a. (Mais adiante, na aula return, você vai ver um jeito ainda mais limpo: pôr a busca numa função e sair dela de uma vez.)
Formas diferentes de fazer a mesma coisa
Para desenhar uma linha de estrelas, o laço de dentro tem um substituto: o texto multiplicado por um número repete o texto (aula Juntar e Repetir Textos). "*" * 3 é "***". O triângulo fica com um laço só:
for linha in range(1, 6):
print("*" * linha)
$ python3 triangulo_mult.py * ** *** **** *****
Mesmo desenho, e sem precisar do end="" nem do print() para pular a linha. Com esse truque, até uma pirâmide fica fácil: cada linha leva alguns espaços antes das estrelas, para centralizar.
altura = 4
for linha in range(1, altura + 1):
espacos = altura - linha
estrelas = 2 * linha - 1
print(" " * espacos + "*" * estrelas)
$ python3 piramide.py * *** ***** *******
Na linha 1: 3 espaços e 1 estrela. Na linha 2: 2 espaços e 3 estrelas. Cada linha tem um espaço a menos e duas estrelas a mais.
| Situação | Qual usar |
|---|---|
| Combinar cada item de um grupo com cada item de outro (fileiras × cadeiras, tabuadas × números) | Laço aninhado |
| Uma linha com N cópias do mesmo caractere | "*" * n, sem laço de dentro |
| Uma linha em que cada posição é diferente (a grade de multiplicação) | Laço de dentro com print(…, end="") e um print() depois |
| Parar tudo no primeiro que achar | break no de dentro + variável achou + break no de fora |
Quando dá errado
for i in range(1, 4):
for i in range(1, 3):
print(i, end=" ")
print(f"<- fim da fileira {i}")
$ python3 mesmo_nome.py 1 2 <- fim da fileira 2 1 2 <- fim da fileira 2 1 2 <- fim da fileira 2
Nenhum erro, mas a fileira é sempre "2". Os dois laços usam o nome i, então o de dentro sobrescreve o valor do de fora. Quando o laço de dentro termina, i ficou com o último valor dele (2), e é esse que o print mostra. (O laço de fora ainda dá as suas 3 voltas, porque o for não usa a variável para saber qual é o próximo item; mas o valor dele se perdeu.) Como consertar: nomes diferentes e que digam o que guardam: for fileira in … e for cadeira in ….
print() que pula a linha
for linha in range(3):
for coluna in range(5):
print("*", end="")
$ python3 sem_print.py ***************ana@notebook:~$ « o prompt grudou no fim das estrelas
As 15 estrelas saíram numa linha só, e até o prompt do terminal ficou grudado nelas. Com end="", nenhum print pula a linha; isso é trabalho do print() vazio no laço de fora. Como consertar: ponha print() com 4 espaços, depois do laço de dentro.
print() entrou no laço de dentro
for linha in range(2):
for coluna in range(3):
print("*", end="")
print()
$ python3 print_dentro.py * * * * * *
Com 8 espaços, o print() faz parte do laço de dentro e pula a linha depois de cada estrela: em vez de 2 linhas de 3, saíram 6 linhas de 1. Como consertar: o print() vai com 4 espaços, alinhado com o for coluna. Num laço aninhado, cada nível de indentação diz em qual laço a linha está.
for linha in range(3):
for coluna in range(5):
print("*", end="")
print()
$ python3 recuo.py
File "/home/ana/recuo.py", line 4
print()
^
IndentationError: unindent does not match any outer indentation level
"Erro de indentação: o recuo não corresponde a nenhum nível de indentação de fora". O print() tem 2 espaços. Os níveis que existem são 0 (o for linha), 4 (o for coluna) e 8 (o print("*")); 2 não é nenhum deles, e o Python não sabe a qual laço a linha pertence. Como consertar: use sempre múltiplos de 4 espaços. Aqui, 4.
Referência rápida
| Escrita | O que faz |
|---|---|
for a in …: / for b in …: | Laço aninhado: o de dentro dá a volta completa a cada volta do de fora |
| voltas de fora × voltas de dentro | Quantas vezes o bloco de dentro roda |
print(x, end="") no de dentro + print() no de fora | Montar uma linha por volta do de fora |
for b in range(a): | O de dentro depende do de fora: linhas de tamanhos diferentes (triângulo) |
f"{n:3}" | O número ocupa 3 casas: colunas alinhadas |
"*" * n | N estrelas sem laço de dentro |
break no de dentro | Sai só do de dentro; o de fora continua |
| Sintoma | Causa provável |
|---|---|
| A variável do de fora mostra um valor errado | Os dois laços usam o mesmo nome de variável |
| Tudo numa linha só | Faltou o print() no laço de fora |
| Um item por linha, em vez de uma tabela | O print() está indentado dentro do laço de dentro |
IndentationError: unindent does not match any outer indentation level | Uma linha com recuo que não é nenhum dos níveis (use múltiplos de 4) |
O break não parou a busca toda | Ele só sai do laço de dentro: use a variável achou |
Exercícios
1. Quantas vezes?
Quantas vezes aparece Oi?
for a in range(4):
for b in range(5):
print("Oi")
2. Complete o triângulo
Complete para o laço de dentro dar tantas voltas quanto o número da linha:
for estrela in range():
print("*", end="")
print()
3. Num laço aninhado, o que acontece com o laço de dentro a cada nova volta do de fora?
4. Um break está dentro do laço de dentro. O que ele faz?
5. Este programa mostra 15 estrelas numa linha só: for l in range(3): / for c in range(5): / print("*", end=""). O que falta para virar um retângulo 3 × 5?
Missão final: o triângulo de estrelas
Missão: este programa desenha um quadrado de 5 × 5. Mude o laço de dentro para desenhar um triângulo: 1 estrela na primeira linha, 2 na segunda… até 5 na quinta. Use dois for (sem o atalho "*" * n).
for linha in range(1, 6):
for estrela in range(5):
print("*", end="")
print()
for linha in range(1, 6):
for estrela in range(linha):
print("*", end="")
print()
Conseguiu? Agora tente o desafio: o triângulo invertido, ou o triângulo "encostado à direita" (espaços antes das estrelas, como na pirâmide).
Resumo
- Um laço aninhado é um laço dentro do bloco de outro. O de dentro dá a volta completa a cada volta do de fora; o bloco de dentro roda (voltas de fora × voltas de dentro) vezes.
- A indentação diz em qual laço cada linha está: 4 espaços para o de fora, 8 para o de dentro.
- Tabelas e desenhos:
print(…, end="")no de dentro para montar a linha,print()no de fora para pulá-la. - Se o de dentro usar a variável do de fora (
range(linha)), cada linha fica de um tamanho: é o triângulo. - O
breaksó sai do laço de dentro; para parar tudo, use uma variávelachoue um segundobreak. - Dê nomes diferentes às variáveis dos dois laços (
fileiraecadeira), senão o de dentro apaga o valor do de fora.