Mémo

La boucle for : parcours d'une séquence
for element in sequence:
    bloc   # exécuté pour chaque élément de la séquence
  • range(n) : entiers de 0 à n-1 ;
  • range(a, b) : entiers de a à b-1 ;
  • range(a, b, p) : de a à b-1 avec un pas de p.

On utilise la boucle for quand le nombre d'itérations est connu à l'avance.

La boucle while : tant que…
while condition:
    bloc   # exécuté tant que la condition est vraie
  • On utilise while quand le nombre d'itérations est inconnu à l'avance ;
  • Le bloc doit modifier une variable pour que la condition finisse par devenir fausse (sinon boucle infinie) ;
  • break sort immédiatement de la boucle ;
  • continue passe directement à l'itération suivante.
Accumulateurs et compteurs

Deux schémas fondamentaux :

# Accumulateur : on accumule un résultat
total = 0
for x in liste:
    total = total + x      # ou total += x

# Compteur : on compte les éléments vérifiant une condition
compteur = 0
for x in liste:
    if condition(x):
        compteur += 1
Pièges fréquents
  • range(5) ne contient pas 5 (la borne supérieure est exclue) ;
  • Oublier d'incrémenter la variable de contrôle dans un while, ce qui provoque une boucle infinie ;
  • Modifier une liste en la parcourant avec for (comportement imprévisible) ;
  • Confondre for i in range(len(L)) (parcours par indice) et for x in L (parcours par valeur).

Exemples

Somme des entiers de 1 à n (accumulateur)
def somme(n):
    total = 0
    for i in range(1, n + 1):
        total += i
    return total
Table de multiplication
def table(n):
    for i in range(1, 11):
        print(f"{n} × {i} = {n * i}")
Compter les voyelles d'un mot (compteur)
def nb_voyelles(mot):
    compteur = 0
    for lettre in mot:
        if lettre.lower() in "aeiouy":
            compteur += 1
    return compteur
Boucle while : deviner un nombre
import random
secret = random.randint(1, 100)
tentative = 0
while tentative != secret:
    tentative = int(input("Proposition : "))
    if tentative < secret:
        print("Plus grand !")
    elif tentative > secret:
        print("Plus petit !")
print("Bravo !")
Boucle while : suite de Syracuse
def syracuse(n):
    etapes = 0
    while n != 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3 * n + 1
        etapes += 1
    return etapes
Boucles imbriquées
for i in range(1, 6):
    for j in range(1, 6):
        print(f"{i*j:4}", end="")
    print()   # retour à la ligne après chaque ligne du tableau

Exercices

Exercice 1 — Somme et produit
2 pts
  1. Écrire une fonction somme_carres(n) qui renvoie $1^2 + 2^2 + \cdots + n^2$.
  2. Écrire une fonction factorielle(n) qui renvoie $n! = 1 × 2 × \cdots × n$.
Voir la solution
def somme_carres(n):
    total = 0
    for i in range(1, n + 1):
        total += i ** 2
    return total

def factorielle(n):
    produit = 1
    for i in range(1, n + 1):
        produit *= i
    return produit

Vérification : somme_carres(3) = $1 + 4 + 9 = 14$. factorielle(5) = $120$.

On peut vérifier avec la formule : $\sum_{k=1}^{n} k^2 = \dfrac{n(n+1)(2n+1)}{6}$, pour $n = 3$ : $\dfrac{3 × 4 × 7}{6} = 14$. ✓

Exercice 2 — Compter et filtrer
3 pts
  1. Écrire une fonction nb_diviseurs(n) qui renvoie le nombre de diviseurs d'un entier positif n.
  2. En déduire une fonction est_premier(n) qui teste si n est premier.
  3. Écrire une fonction premiers_jusqu_a(n) qui renvoie la liste des nombres premiers inférieurs ou égaux à n.
Voir la solution
def nb_diviseurs(n):
    compteur = 0
    for d in range(1, n + 1):
        if n % d == 0:
            compteur += 1
    return compteur

def est_premier(n):
    if n < 2:
        return False
    return nb_diviseurs(n) == 2

def premiers_jusqu_a(n):
    resultat = []
    for k in range(2, n + 1):
        if est_premier(k):
            resultat.append(k)
    return resultat

Vérification :

  • nb_diviseurs(12) renvoie 6 (diviseurs : 1, 2, 3, 4, 6, 12) ;
  • est_premier(7) renvoie True ;
  • premiers_jusqu_a(20) renvoie [2, 3, 5, 7, 11, 13, 17, 19].

Remarque : cette version est correcte mais peu efficace. On pourrait optimiser est_premier en ne testant les diviseurs que jusqu'à $\sqrt{n}$.

Exercice 3 — Boucle while
3 pts
  1. Écrire une fonction nb_chiffres(n) qui renvoie le nombre de chiffres d'un entier positif n (sans utiliser str).
  2. Écrire une fonction somme_chiffres(n) qui renvoie la somme des chiffres de n.
  3. Écrire une fonction miroir(n) qui renvoie l'entier obtenu en inversant les chiffres de n. Par exemple, miroir(1234) renvoie 4321.
Voir la solution
def nb_chiffres(n):
    if n == 0:
        return 1
    compteur = 0
    while n > 0:
        n = n // 10
        compteur += 1
    return compteur

def somme_chiffres(n):
    total = 0
    while n > 0:
        total += n % 10    # dernier chiffre
        n = n // 10         # on retire le dernier chiffre
    return total

def miroir(n):
    resultat = 0
    while n > 0:
        resultat = resultat * 10 + n % 10
        n = n // 10
    return resultat

Principe commun : n \% 10 extrait le dernier chiffre et n // 10 le retire.

Trace de miroir(1234) :

  • Étape 1 : resultat = 0 * 10 + 4 = 4, n = 123
  • Étape 2 : resultat = 4 * 10 + 3 = 43, n = 12
  • Étape 3 : resultat = 43 * 10 + 2 = 432, n = 1
  • Étape 4 : resultat = 432 * 10 + 1 = 4321, n = 0
Exercice 4 — Boucles imbriquées
2 pts

Écrire une fonction triangle(n) qui affiche un triangle d'étoiles :

*
**
***
****
*****

pour n = 5.

Voir la solution
def triangle(n):
    for i in range(1, n + 1):
        print("*" * i)

Remarque : en Python, "*" * i répète la chaîne i fois, ce qui évite une boucle interne. La version avec boucle imbriquée serait :

def triangle(n):
    for i in range(1, n + 1):
        for j in range(i):
            print("*", end="")
        print()