2.12. Laços

Um laço executa o mesmo bloco de código repetidamente. O Python tem duas formas: while, que continua enquanto uma condição permanece verdadeira, e for, que percorre os itens de uma sequência.

Fluxogramas lado a lado. while: testa a condição, executa o corpo se verdadeira, repete. for: pega o próximo item do iterável, executa o corpo, repete até esgotar.

O while continua testando uma condição; o for percorre uma sequência até esgotá-la.

2.12.1. Laços while

Um laço while testa sua condição antes de cada iteração e executa o corpo até que o teste se torne falso:

count = 0
while count < 5:
    print(count)
    count += 1

Saída:

0
1
2
3
4

Se a condição for verdadeira no início e nunca se tornar falsa, o laço roda para sempre. while True: é o idiom padrão para um laço principal, do qual se sai explicitamente com break:

while True:
    step()
    if done():
        break

2.12.2. Laços for

Um laço for percorre os itens de um iterável – uma lista, tupla, string, bytes, dict ou qualquer outra coisa que suporte iteração:

for fruit in ["apple", "banana", "cherry"]:
    print(fruit)

Saída:

apple
banana
cherry

A mesma forma funciona em uma string, onde cada item é uma string de um caractere:

for letter in "OpenMV":
    print(letter)

Saída:

O
p
e
n
M
V

Iterar um dict diretamente produz suas chaves, na ordem de inserção:

for key in {"a": 1, "b": 2}:
    print(key)

Saída:

a
b

Cada passagem associa a variável do laço (fruit, letter, key) ao próximo item. Após o término do laço, a variável mantém o valor da iteração final.

2.12.3. range

Para laços sobre um intervalo numérico, use range():

  • range(stop) – 0, 1, …, stop - 1.

  • range(start, stop) – start, start + 1, …, stop - 1.

  • range(start, stop, step) – com um passo personalizado (valores negativos contam para baixo).

for i in range(5):           # 0, 1, 2, 3, 4
    print(i)

for i in range(2, 8, 2):     # 2, 4, 6
    print(i)

for i in range(10, 0, -1):   # 10, 9, ..., 1
    print(i)

range() produz valores de forma preguiçosa – não constrói uma lista na memória. Para obter uma list de fato, envolva-o: list(range(10)).

2.12.4. enumerate

Quando o laço precisa tanto do índice quanto do item, enumerate() produz pares (index, item):

for i, name in enumerate(["a", "b", "c"]):
    print(i, name)
# 0 a
# 1 b
# 2 c

Inicie o índice em algo diferente de zero passando um segundo argumento: enumerate(items, start=1).

2.12.5. zip

Para percorrer dois (ou mais) iteráveis em sincronia, use zip(). Ele produz uma tupla por posição e para na entrada mais curta:

names  = ["alice", "bob", "carol"]
scores = [88, 92, 70]

for name, score in zip(names, scores):
    print(name, score)

Saída:

alice 88
bob 92
carol 70

2.12.6. Atribuição em linha com :=

O operador morsa := é uma atribuição que também é uma expressão. Ele associa um nome e avalia para o mesmo valor ao mesmo tempo. Em um laço while, isso reduz o padrão comum de “ler, verificar, corpo” a uma única linha:

# without walrus
value = next_value()
while value is not None:
    process(value)
    value = next_value()

# with walrus
while (value := next_value()) is not None:
    process(value)

As duas formas fazem a mesma coisa. Recorra ao := quando a duplicação da atribuição realmente prejudicar a legibilidade; não o use apenas para parecer esperto. Os parênteses são obrigatórios na maioria das posições para manter a expressão sem ambiguidade.