Structures de contrôle#
if / elif / else#
La structure conditionnelle if est le mécanisme fondamental qui permet à un programme de prendre des décisions. En Python, cette structure repose sur l”indentation pour délimiter les blocs de code — là où d’autres langages utilisent des accolades {}. Cette règle n’est pas un choix arbitraire : elle garantit que la structure visuelle du code reflète toujours sa structure logique, rendant la lecture intuitive.
temperature = 18
if temperature < 0:
print("Il gèle : mettez un manteau chaud.")
elif temperature < 10:
print("Il fait froid : prenez une veste.")
elif temperature < 20:
print("Temps frais : un pull suffira.")
elif temperature < 30:
print("Agréable : habits légers.")
else:
print("Canicule : restez à l'ombre et hydratez-vous.")
Temps frais : un pull suffira.
Remarque 7
L’indentation en Python est syntaxiquement obligatoire : c’est ce qui définit les blocs. La convention PEP 8 prescrit 4 espaces par niveau d’indentation (et non des tabulations). Mélanger espaces et tabulations dans un même fichier est une erreur de syntaxe en Python 3. La plupart des éditeurs modernes configurés pour Python convertissent automatiquement les tabulations en espaces.
Expressions conditionnelles ternaires#
Python propose une forme condensée pour les conditions simples, l”expression conditionnelle (souvent appelée opérateur ternaire), qui permet d’écrire une condition sur une seule ligne :
# Forme longue
age = 20
if age >= 18:
statut = "majeur"
else:
statut = "mineur"
# Forme ternaire équivalente
statut = "majeur" if age >= 18 else "mineur"
print(statut)
# Usages courants
maximum = a if (a := 15) > (b := 10) else b
print(f"Maximum de {a} et {b} : {maximum}")
# Calcul conditionnel
prix_ttc = lambda prix_ht: prix_ht * 1.20 if prix_ht > 0 else 0
print(prix_ttc(100))
majeur
Maximum de 15 et 10 : 15
120.0
Définition 4 (Expression vs instruction)
En Python, une instruction (statement) est une unité d’exécution qui ne produit pas de valeur (comme if, for, while, def). Une expression est une unité qui s’évalue en une valeur (comme x + 1, "bonjour".upper(), True if x > 0 else False). L’expression conditionnelle ternaire (valeur_si_vrai if condition else valeur_si_faux) est une expression : elle peut apparaître partout où une valeur est attendue — dans une assignation, un appel de fonction, une compréhension.
La boucle while#
La boucle while répète un bloc de code tant qu’une condition est vraie. Elle est adaptée aux situations où le nombre d’itérations n’est pas connu à l’avance.
# Exemple : algorithme d'Euclide pour le PGCD
def pgcd(a, b):
while b != 0:
a, b = b, a % b
return a
print(pgcd(48, 18)) # 6
print(pgcd(100, 75)) # 25
6
25
break et continue#
# break : sortir immédiatement de la boucle
n = 0
while True: # boucle infinie contrôlée par break
n += 1
if n > 5:
break
print(f"Sorti de la boucle à n = {n}")
# continue : passer à l'itération suivante
i = 0
résultats = []
while i < 10:
i += 1
if i % 2 == 0:
continue # Ignorer les pairs
résultats.append(i)
print(f"Nombres impairs : {résultats}")
Sorti de la boucle à n = 6
Nombres impairs : [1, 3, 5, 7, 9]
La clause else sur while#
Python offre une fonctionnalité originale : une clause else sur les boucles. Le bloc else est exécuté uniquement si la boucle s’est terminée normalement, c’est-à-dire sans être interrompue par un break.
# Recherche avec while ... else
def chercher_diviseur(n, limite):
d = 2
while d <= limite:
if n % d == 0:
print(f"{n} est divisible par {d}")
break
d += 1
else:
print(f"Aucun diviseur trouvé jusqu'à {limite}")
chercher_diviseur(15, 10)
chercher_diviseur(17, 10)
15 est divisible par 3
Aucun diviseur trouvé jusqu'à 10
Remarque 8
La clause else sur les boucles est l’une des fonctionnalités les plus déroutantes pour les nouveaux venus en Python, mais elle s’avère très utile dans des algorithmes de recherche. Une façon de la lire : « la boucle s’est terminée sans trouver ce qu’elle cherchait ». Elle évite d’avoir à utiliser un drapeau booléen (trouvé = False) pour détecter si un break a eu lieu.
La boucle for#
La boucle for en Python n’est pas une boucle à compteur comme en C ou Java : c’est une boucle d”itération sur une séquence (ou tout objet itérable). Cette distinction est fondamentale et explique la puissance et l’élégance du for Python.
# Itération sur une liste
fruits = ["pomme", "banane", "cerise", "datte"]
for fruit in fruits:
print(f"- {fruit}")
- pomme
- banane
- cerise
- datte
range()#
range() génère une séquence d’entiers à la demande, sans créer de liste en mémoire :
# range(stop) : de 0 à stop-1
for i in range(5):
print(i, end=" ")
print()
# range(start, stop) : de start à stop-1
for i in range(2, 8):
print(i, end=" ")
print()
# range(start, stop, step) : avec un pas
for i in range(0, 20, 3):
print(i, end=" ")
print()
# Compter à rebours
for i in range(10, 0, -2):
print(i, end=" ")
print()
0 1 2 3 4
2 3 4 5 6 7
0 3 6 9 12 15 18
10 8 6 4 2
enumerate() et zip()#
# enumerate() : indice + valeur simultanément
langages = ["Python", "Rust", "Go", "TypeScript"]
for i, langage in enumerate(langages, start=1):
print(f"{i}. {langage}")
1. Python
2. Rust
3. Go
4. TypeScript
# zip() : itérer sur plusieurs séquences en parallèle
noms = ["Alice", "Bob", "Charlie"]
notes = [18, 14, 16]
matieres = ["Maths", "Physique", "Informatique"]
for nom, note, matiere in zip(noms, notes, matieres):
print(f"{nom} a eu {note}/20 en {matiere}")
# zip s'arrête à la plus courte séquence
# Pour toutes les longueurs : itertools.zip_longest
Alice a eu 18/20 en Maths
Bob a eu 14/20 en Physique
Charlie a eu 16/20 en Informatique
La clause else sur for#
def est_premier(n):
if n < 2:
return False
for d in range(2, int(n**0.5) + 1):
if n % d == 0:
break
else:
return True
return False
print([n for n in range(2, 30) if est_premier(n)])
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
match / case (Python 3.10+)#
Introduit en Python 3.10 par la PEP 634, le match/case apporte le filtrage structurel (structural pattern matching). Il va bien au-delà d’un simple switch/case : il peut décomposer des structures de données complexes, capturer des variables, tester des types et des gardes conditionnelles, le tout de façon déclarative et lisible.
Définition 5 (Filtrage structurel)
Le filtrage structurel est une technique qui permet de tester simultanément la forme et le contenu d’une valeur, en capturant des parties de cette valeur dans des variables. Contrairement à une succession de if/elif, le match/case Python ne se contente pas de comparer des valeurs scalaires : il peut décomposer des listes, des tuples, des objets et des dictionnaires en une seule expression.
Patterns de valeur et de capture#
def analyser_commande(commande):
match commande:
case "quitter":
return "Au revoir !"
case "aide":
return "Commandes disponibles : quitter, aide, version"
case "version":
return "Python 3.12"
case _: # Wildcard : correspond à tout
return f"Commande inconnue : {commande!r}"
print(analyser_commande("quitter"))
print(analyser_commande("aide"))
print(analyser_commande("inconnu"))
Au revoir !
Commandes disponibles : quitter, aide, version
Commande inconnue : 'inconnu'
Patterns de séquence#
def traiter_point(point):
match point:
case (0, 0):
return "Origine"
case (x, 0):
return f"Sur l'axe X, x = {x}"
case (0, y):
return f"Sur l'axe Y, y = {y}"
case (x, y):
return f"Point en ({x}, {y})"
case _:
return "Pas un point valide"
print(traiter_point((0, 0)))
print(traiter_point((3, 0)))
print(traiter_point((2, 5)))
Origine
Sur l'axe X, x = 3
Point en (2, 5)
# Patterns de séquence avec longueur variable
def analyser_liste(lst):
match lst:
case []:
return "Liste vide"
case [seul]:
return f"Un seul élément : {seul}"
case [premier, *reste]:
return f"Premier : {premier}, reste : {reste}"
print(analyser_liste([]))
print(analyser_liste([42]))
print(analyser_liste([1, 2, 3, 4, 5]))
Liste vide
Un seul élément : 42
Premier : 1, reste : [2, 3, 4, 5]
Patterns de classe et gardes if#
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
@dataclass
class Cercle:
centre: Point
rayon: float
def décrire_forme(forme):
match forme:
case Point(x=0, y=0):
return "Point à l'origine"
case Point(x=x, y=y) if x == y:
return f"Point sur la diagonale : ({x}, {y})"
case Point(x=x, y=y):
return f"Point quelconque : ({x}, {y})"
case Cercle(rayon=r) if r <= 0:
return "Rayon invalide"
case Cercle(centre=c, rayon=r):
return f"Cercle de rayon {r} centré en ({c.x}, {c.y})"
case _:
return "Forme inconnue"
print(décrire_forme(Point(0, 0)))
print(décrire_forme(Point(3, 3)))
print(décrire_forme(Point(1, 5)))
print(décrire_forme(Cercle(Point(0, 0), 5)))
Point à l'origine
Point sur la diagonale : (3, 3)
Point quelconque : (1, 5)
Cercle de rayon 5 centré en (0, 0)
Compréhensions#
Les compréhensions sont une syntaxe concise et très pythonique pour construire des collections à partir d’itérables existants, avec un filtrage optionnel. Elles sont souvent plus lisibles et plus rapides que les boucles for équivalentes.
Compréhensions de liste#
# Forme générale : [expression for variable in itérable if condition]
# Sans filtre
carrés = [x**2 for x in range(10)]
print(carrés)
# Avec filtre
carrés_pairs = [x**2 for x in range(10) if x % 2 == 0]
print(carrés_pairs)
# Imbriquée : produit cartésien
paires = [(x, y) for x in range(3) for y in range(3) if x != y]
print(paires)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 4, 16, 36, 64]
[(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
Compréhensions de dictionnaire et d’ensemble#
# Compréhension de dictionnaire
mots = ["bonjour", "monde", "python", "génial"]
longueurs = {mot: len(mot) for mot in mots}
print(longueurs)
# Inverser un dictionnaire
original = {"a": 1, "b": 2, "c": 3}
inverse = {v: k for k, v in original.items()}
print(inverse)
# Compréhension d'ensemble (élimine automatiquement les doublons)
nombres = [1, 2, 2, 3, 3, 3, 4]
ensemble = {x**2 for x in nombres}
print(ensemble)
{'bonjour': 7, 'monde': 5, 'python': 6, 'génial': 6}
{1: 'a', 2: 'b', 3: 'c'}
{16, 1, 4, 9}
Expressions génératrices#
# Une expression génératrice est comme une compréhension de liste
# mais ne crée pas toute la liste en mémoire : elle génère les éléments
# à la demande (évaluation paresseuse)
# Somme sans créer de liste intermédiaire
total = sum(x**2 for x in range(1_000_000))
print(total)
# La parenthèse extérieure suffit quand c'est l'unique argument
premier_pair = next(x for x in range(100) if x % 2 == 0 and x > 10)
print(premier_pair)
333332833333500000
12
Remarque 9
Les expressions génératrices sont préférables aux compréhensions de liste lorsque la collection n’est parcourue qu’une seule fois et qu’on n’a pas besoin de la stocker en entier. Elles consomment une mémoire constante, indépendamment de la taille de l’itérable source — un avantage décisif pour les grands jeux de données. En revanche, elles ne peuvent être parcourues qu’une seule fois : après épuisement, l’itérateur est vide.
Visualisation des patterns match/case#
Résumé#
Dans ce chapitre, nous avons parcouru l’ensemble des structures de contrôle de Python :
Le
if/elif/elseutilise l”indentation obligatoire pour délimiter les blocs. L”expression ternaire (valeur_a if condition else valeur_b) permet d’écrire des conditions simples en une ligne.La boucle
whilerépète tant qu’une condition est vraie.breakl’interrompt immédiatement,continuepasse à l’itération suivante. La clauseelsesurwhileest exécutée uniquement si la boucle s’est terminée sansbreak.La boucle
foritère sur n’importe quel itérable.range()génère des séquences d’entiers à la demande.enumerate()fournit l’indice et la valeur simultanément ;zip()permet d’itérer sur plusieurs séquences en parallèle. La clauseelsesurforfonctionne de même que surwhile.Le
match/case(Python 3.10+) apporte le filtrage structurel : il peut décomposer des valeurs littérales, des séquences, des objets (classes), capturer des variables, et se raffiner avec des gardesif. C’est un outil puissant pour gérer des structures de données complexes de façon déclarative.Les compréhensions (de liste, de dictionnaire, d’ensemble) sont une syntaxe concise pour construire des collections avec filtrage optionnel. Les expressions génératrices sont leur équivalent paresseux, qui consomment une mémoire constante.
Dans le chapitre suivant, nous aborderons les fonctions : définition, paramètres avancés, portée des variables, fonctions de première classe et récursion.