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.

Você vai aprender
  • 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 break só 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 o IndentationError.

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:

  1. Vai para a fileira A e confere as cadeiras 1, 2, 3 e 4.
  2. Só então passa para a fileira B e confere as cadeiras 1, 2, 3 e 4 de novo.
  3. 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.

Quantas vezes o bloco de dentro roda?

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 foralinhaO de dentro: range(linha)Estrelas
1ª1range(1): 1 volta*
2ª2range(2): 2 voltas**
3ª3range(3): 3 voltas***
4ª4range(4): 4 voltas****
5ª5range(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çãoQual 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 acharbreak no de dentro + variável achou + break no de fora

Quando dá errado

A mesma variável nos dois laços
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 ….

Esqueceu o 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.

O 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á.

Indentação que não bate com nenhum nível
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

EscritaO 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 dentroQuantas vezes o bloco de dentro roda
print(x, end="") no de dentro + print() no de foraMontar 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
"*" * nN estrelas sem laço de dentro
break no de dentroSai só do de dentro; o de fora continua
SintomaCausa provável
A variável do de fora mostra um valor erradoOs 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 tabelaO print() está indentado dentro do laço de dentro
IndentationError: unindent does not match any outer indentation levelUma linha com recuo que não é nenhum dos níveis (use múltiplos de 4)
O break não parou a busca todaEle 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")
vezes.

2. Complete o triângulo

Complete para o laço de dentro dar tantas voltas quanto o número da linha:

for linha in range(1, 6):
    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 break só sai do laço de dentro; para parar tudo, use uma variável achou e um segundo break.
  • Dê nomes diferentes às variáveis dos dois laços (fileira e cadeira), senão o de dentro apaga o valor do de fora.