Terminale NSI — Programmation fonctionnelle
Séance 4 — Structures de données immuables
1. Mutable ou immuable ?
Mutables : list, dict, set
Immuables : tuple, str, frozenset, int, float, bool, None
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4] !
Piège — aliasing
b = a ne copie pas la liste : b et a référencent le même objet.2. Exercice 1 — Ensembles et opérations non destructives
invites_alice = {"Bob", "Chloé", "David"}
invites_eva = {"Chloé", "David", "Farid"}
a) Union (|). b) Intersection (&). c) Différence (-). d) Les ensembles de départ ont-ils changé ?
Voir la réponse
union = invites_alice | invites_eva
intersection = invites_alice & invites_eva
difference = invites_alice - invites_eva
Non : |, & et - créent un nouvel ensemble sans jamais modifier les ensembles de départ (opérations non destructives).
3. Exercice 2 — L'agence spatiale (version immuable)
def deplacer(position, dx, dy, dz):
"""Renvoie une NOUVELLE position, sans modifier position."""
...
vaisseau1 = (0, 0, 0)
nouvelle_position = deplacer(vaisseau1, 10, 0, 5)
a) Complète deplacer. b) vaisseau1 a-t-il changé ? c) Que se passe-t-il si tu écris vaisseau1[0] = 5 ?
Voir la réponse
def deplacer(position, dx, dy, dz):
x, y, z = position
return (x + dx, y + dy, z + dz)
vaisseau1[0] = 5 lève une TypeError : un tuple est immuable, aucune opération ne permet de modifier un de ses éléments en place.
4. Exercice 3 — L'agence spatiale (version mutable, le bug)
position_origine = [0, 0, 0]
flotte = [position_origine] * 3
flotte[0][0] = 100
print(flotte)
a) Prédis le résultat. b) Explique avec id(). c) Corrige avec .copy(). d) Ce bug peut-il arriver avec des tuples ?
Voir la réponse
Résultat réel :
[[100,0,0],[100,0,0],[100,0,0]] — [position_origine] * 3 crée 3 références vers le même objet liste.
flotte = [position_origine.copy() for _ in range(3)]
Avec des tuples, ce bug est impossible : même si les références sont partagées, un tuple ne peut jamais être modifié en place. L'immuabilité élimine structurellement ce bug.
Exercices défis (bonus)
Défi 1 défi
t = (1, [2, 3]). Peux-tu faire t[0]=5 ? Et t[1].append(4) ?
Voir la réponse
t[0]=5 échoue (TypeError). t[1].append(4) fonctionne : le tuple est immuable sur ses références, pas récursivement sur le contenu de celles-ci.
Défi 2 défi
Recherche collections.namedtuple et crée un type Position(x, y, z).
Voir la réponse
from collections import namedtuple
Position = namedtuple("Position", ["x", "y", "z"])
p = Position(10, 0, 5)
print(p.x) # plus lisible que p[0]
Défi 3 défi
Écris fusionner_flottes(flotte1, flotte2) sans jamais modifier les originales.
Voir la réponse
return flotte1 + flotte2 — la concaténation de tuples crée un nouveau tuple.