Adloun

Prédire, puis vérifier, l'effet de chacune de ces quatre séquences

Exercice supplémentaire · niveau 3 (difficile) · NSI (première), chapitre 4 — Les types construits · Références partagées, copies et effets de bord

Énoncé

Prédire, puis vérifier, l'effet de chacune de ces quatre séquences. En déduire ce que copie exactement list(t), et comment copier vraiment une matrice.


t1 = [1, 2, 3]                     # puis, separement :
t2 = t1              ; t2[0] = 99
t3 = list(t1)        ; t3[0] = 0

m1 = [[1, 2], [3, 4]]              # puis, separement :
m2 = list(m1)                  ; m2[0][0] = 99
m3 = [list(l) for l in m1]     ; m3[0][0] = 7

Corrigé


t1 = [1, 2, 3]
t2 = t1                 # AUCUNE copie : deux noms, un seul tableau
t2[0] = 99
print(t1)               # [99, 2, 3]   <- t1 a change

t3 = list(t1)           # une copie du tableau
t3[0] = 0
print(t1, t3)           # [99, 2, 3] [0, 2, 3]   <- independants

Sur un tableau de nombres, list(t) suffit. Sur une matrice, non :


m1 = [[1, 2], [3, 4]]
m2 = list(m1)           # copie SUPERFICIELLE
m2[0][0] = 99
print(m1)               # [[99, 2], [3, 4]]   <- m1 a change !

m3 = [list(ligne) for ligne in m1]   # copie ligne par ligne
m3[0][0] = 7
print(m1, m3)           # [[99, 2], [3, 4]] [[7, 2], [3, 4]]   <- independants

Ce que copie list(t). Le tableau extérieur, et lui seul. La nouvelle case contient une référence vers le même tableau intérieur que l'ancienne. Sur des nombres, cela ne se voit pas : un entier ne se modifie pas, on ne peut que le remplacer. Sur des tableaux, cela se voit tout de suite — et c'est exactement le mécanisme du piège [[0] <em> 2] </em> 3.

Trois niveaux, à distinguer une fois pour toutes :

ÉcritureCe qui est copiéLa copie modifiée touche l'original ?
`m2 = m1`rienoui, toujours
`m2 = list(m1)`le tableau extérieuroui, par les lignes
`[list(l) for l in m1]`toutnon

Hors programme, la bibliothèque standard offre copy.deepcopy(m), qui copie récursivement à toute profondeur. Sur les matrices de nombres du programme, la compréhension suffit et se lit mieux. Le test décisif reste m1[0] is m2[0] : s'il rend True, on n'a pas copié ce qu'on croyait.

Les autres exercices de ce chapitre Le cours du chapitre

Un blocage sur cet exercice ? Le tuteur d'Adloun guide par questions, sans donner la réponse.