Chapter 15, Basic
Loops with for
The `for` iterates over any collection. Almost whenever you think about counting indices, there is a better way to write it.
Code for this chapter: basico/cap15_laco_for.py
for in any iterable
The for in Python does not count: it iterates over the items of any iterable object (string, list, file, dictionary):
for letra in "abc":
print(letra)
for fruta in ["maçã", "pera"]:
print(fruta)
a
b
c
maçã
pera
range
When you need a sequence of numbers, use range. It accepts range(fim), range(inicio, fim) and range(inicio, fim, passo), and the end is never included. It is lazy: it does not create the list in memory. The list() below serves only to show the content:
print(list(range(5)))
print(list(range(1, 6)))
print(list(range(0, 10, 2)))
print(list(range(5, 0, -1)))
[0, 1, 2, 3, 4]
[1, 2, 3, 4, 5]
[0, 2, 4, 6, 8]
[5, 4, 3, 2, 1]
enumerate and zip
Do not write for i in range(len(lista)) to get the position. The enumerate delivers position and item together. The zip iterates two sequences in parallel:
nomes = ["Ana", "Bia", "Caio"]
for posicao, nome in enumerate(nomes, start=1):
print(posicao, nome)
notas = [9, 8, 7]
for nome, nota in zip(nomes, notas):
print(f"{nome}: {nota}")
1 Ana
2 Bia
3 Caio
Ana: 9
Bia: 8
Caio: 7
break, continue and else
The break ends the loop. The continue skips to the next iteration. The else of the loop is little known and very useful: it runs only if the loop finished without break.
for numero in range(1, 11):
if numero == 3:
continue
if numero == 6:
break
print(numero)
else:
print("terminou sem break")
1
2
4
5
The else The loop shines in searches. To know if a number is prime, look for a divisor. If you find one, break. If the loop ends without finding one, the else confirms:
numero = 17
for divisor in range(2, numero):
if numero % divisor == 0:
print(f"{numero} não é primo")
break
else:
print(f"{numero} é primo")
17 é primo
Nested loops and patterns
A loop inside another executes the inner one completely on each turn of the outer. It is the basis of tables, matrices, and patterns drawn with text:
for linhas in range(1, 5):
print("*" * linhas)
*
**
***
****
for i in range(1, 4):
for j in range(1, 4):
print(f"{i} x {j} = {i * j}", end=" ")
print()
1 x 1 = 1 1 x 2 = 2 1 x 3 = 3
2 x 1 = 2 2 x 2 = 4 2 x 3 = 6
3 x 1 = 3 3 x 2 = 6 3 x 3 = 9
Multiplying a string by an integer ("*" * 3) repeats the text, and it is the trick that avoids a second loop in many designs.
Exercise 1
Factorial
Write fatorial(n) with a loop for. The factorial of 0 is 1.
Exercise 2
Diamond of asterisks
Write diamante(n) that returns a list of lines. For n = 3, the result should be [" *", " ***", "*****", " ***", " *"].
Exercise 3
Primes up to n
Write primos_ate(n) with a loop inside another and the else of the for.