Cours#
Les types construits
| Programme (BO) | « Types construits » : p-uplets, tableaux indexés (listes) et tableaux de tableaux, dictionnaires (tableaux associatifs). Capacités attendues : écrire une fonction renvoyant un p-uplet ; lire et modifier les éléments d’un tableau par leur index ; construire un tableau par compréhension ; itérer sur les éléments d’un tableau ; représenter des matrices par des tableaux de tableaux ; itérer sur les éléments d’un dictionnaire. |
| Prérequis | les bases de Python : variables, types simples (int, float, bool, str), boucles for/while, fonctions. (→ fiches de révision : ch. 1) |
| Objectifs | savoir regrouper des données dans le bon type construit, y accéder, les parcourir et, quand c’est possible, les modifier — en comprenant ce qui se passe en mémoire. Ce chapitre est le socle des chapitres suivants (algorithmique, tris, données en tables…). |
Situation de départ
-
Comment un programme peut-il garder ensemble les 30 notes d’une classe, sans créer 30 variables ?
-
Comment retrouver directement le numéro de casier de Hugo, sans chercher à quelle place il se trouve dans une liste ?
-
Après
copie = notes, on changecopie[0]: pourquoinotesa-t-elle changé aussi ? Comment faire une vraie copie ?
Remarque — Deux fils conducteurs, à garder en tête tout le chapitre
(1) Le fil rouge. Une variable n’est pas une boîte qui contient une valeur : c’est une étiquette (un nom) qui pointe vers un objet rangé en mémoire. Ce seul dessin — des noms, des flèches, des objets — expliquera tout le chapitre : la copie, le partage accidentel de données, le piège des matrices, et jusqu’aux clés de dictionnaire. On le rappellera par un encadré « Fil rouge ».
(2) Le programme est restreint, mais ces types sont partout : on va donc souvent plus loin. Chaque dépassement est signalé par le badge au-delà du programme — utile, fréquent, mais non exigible au baccalauréat.
Le point de départ : une variable est une flèche#
Jusqu’ici, une variable rangeait une valeur simple : un nombre, un booléen, une chaîne. C’est insuffisant pour stocker les 500 notes d’une classe ou un annuaire. On a besoin de variables dont la valeur regroupe plusieurs valeurs.
Définition 1 — Type construit
Un type construit (ou composé) est un type dont chaque valeur regroupe plusieurs valeurs en un seul objet. Par opposition, int, float, bool et str sont considérés ici comme des types simples.
Avant tout, installons le modèle mental qui va tout éclairer.
Règle 1 — Le modèle mémoire : nom \(longrightarrow\) objet
En Python, l’instruction notes = [12, 8, 15] fait deux choses : elle crée l’objet [12, 8, 15] quelque part en mémoire, puis fait pointer le nom notes vers cet objet. La variable ne contient pas l’objet : elle le désigne.
De cette image découle une distinction fondamentale : peut-on modifier l’objet vers lequel on pointe ?
Définition 2 — Mutable / immuable
Un objet est mutable (modifiable) si l’on peut changer son contenu sans en créer un nouveau : c’est le cas des tableaux (list) et des dictionnaires (dict). Il est immuable sinon : c’est le cas des nombres, des chaînes (str) et des p-uplets (tuple).
Remarque — La chaîne : une collection que vous connaissez déjà
Le type str annonce déjà les séquences : ses caractères sont ordonnés et indexés à partir de \(0\) ; on peut aussi en extraire des tranches (nouveau : ch[3:7] ci-dessous, détaillé avec les tableaux). Ces réflexes vont resservir tels quels.
>>> ch = "Bonjour"
>>> ch[0] # premier caractere (indice 0)
'B'
>>> ch[3:7] # tranche : indices 3 a 6
'jour'
>>> len(ch) # longueur
7
Deux questions, trois types#
Plutôt que d’apprendre trois types par cœur, apprenons à choisir. Devant une collection de données, on se pose deux questions :
| Q1. | Comment vais-je retrouver un élément : par sa position (un indice \(0,1,2\ldots\)) ou par une étiquette que je choisis (une clé) ? |
| Q2. | Cette collection va-t-elle changer après sa création (mutable), ou est-elle figée (immuable) ? |
Les réponses désignent le type à utiliser — c’est la carte de décision du chapitre :
| accès | modifiable ? | à utiliser pour… | |
|---|---|---|---|
tuple (p-uplet) |
par indice | non (immuable) | des données figées, plusieurs valeurs renvoyées |
list (tableau) |
par indice | oui (mutable) | une collection ordonnée qui évolue |
dict (dictionnaire) |
par clé | oui (mutable) | associer une valeur à une étiquette |
↺ Retour sur l'activité. Ce sont les deux questions du tableau rempli dans l’activité « Des données en vrac » : la carte d’identité, figée et lue par position, sera un p-uplet ; la liste de courses, qui change, un tableau ; les casiers, retrouvés par le prénom, un dictionnaire.
On étudie maintenant les trois, dans cet ordre : le plus simple (figé) d’abord, puis le mutable, puis l’accès par clé.
Le p-uplet (tuple) : une collection figée#
Définition 3 — p-uplet
Un p-uplet (type tuple) est une suite ordonnée de \(p\) éléments, de types éventuellement différents, que l’on ne peut pas modifier après création (immuable).
Création : c’est la virgule qui compte#
On sépare les éléments par des virgules ; les parenthèses sont facultatives mais recommandées.
>>> point = (3, 4) # un couple
>>> t = 1, 2, 3, "bonjour" # parentheses sous-entendues
>>> t
(1, 2, 3, 'bonjour')
>>> vide = () # p-uplet vide
>>> singleton = (3,) # UN element : la virgule est OBLIGATOIRE
>>> type((3)), type((3,)) # sans virgule, (3) est juste l'entier 3
(<class 'int'>, <class 'tuple'>)
Accès : indice, tranche, len, in#
Comme pour les chaînes : indices à partir de \(0\), indices négatifs depuis la fin, tranches.
>>> t = (10, 20, 30, 40, 50)
>>> t[0], t[-1] # premier, dernier
(10, 50)
>>> t[1:4] # indices 1, 2, 3 (4 exclu)
(20, 30, 40)
>>> len(t)
5
>>> 20 in t # test d'appartenance
True
Immuable : toute modification est refusée#
>>> t = (1, 2, 3)
>>> t[0] = 99
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
Remarque — À quoi sert un type qu’on ne peut pas modifier ?
À garantir qu’une donnée ne bougera pas par erreur : coordonnées d’un point, date, couleur RVB. Et — on le verra au § VI — seul un objet immuable peut servir de clé de dictionnaire.
Affectation multiple : déballer un p-uplet#
Le p-uplet permet d’affecter plusieurs variables en une seule fois : on « déballe » ses composantes dans autant de variables.
>>> a, b, c = 1, 2, 3 # a vaut 1, b vaut 2, c vaut 3
C’est exactement ainsi qu’on récupère les différentes valeurs renvoyées par une fonction (paragraphe suivant).
Une fonction qui renvoie un p-uplet (capacité attendue)#
L’usage numéro un : renvoyer plusieurs résultats d’un coup, récupérés par affectation multiple.
def division(a, b):
"""Renvoie (quotient, reste) de la division entiere de a par b."""
return a // b, a % b
q, r = division(25, 7) # q vaut 3, r vaut 4
Exemple — Renvoyer le minimum et le maximum
def mini_maxi(t):
"""Renvoie (plus petit, plus grand) du tableau non vide t."""
mini = t[0]
maxi = t[0]
for x in t:
if x < mini:
mini = x
if x > maxi:
maxi = x
return mini, maxi
petit, grand = mini_maxi([7, 2, 9, 4]) # petit = 2, grand = 9
▶ Exercices d'application : exercices 1 à 5 (les p-uplets)
Le tableau (list) : ordonné et modifiable#
Un tableau ressemble à un p-uplet… mais il est mutable. C’est là que le fil rouge devient indispensable.
Création#
Définition 4 — Tableau
Un tableau (type list) est une suite ordonnée et modifiable d’éléments, entre crochets.
>>> notes = [12, 8, 15, 9]
>>> vide = []
>>> singleton = [3] # un element : PAS de virgule (contrairement au tuple)
>>> [0] * 5 # repetition : cinq zeros
[0, 0, 0, 0, 0]
Lire et modifier par indice (capacité attendue)#
>>> notes = [12, 8, 15, 9]
>>> notes[1] # lecture
8
>>> notes[1] = 20 # ECRITURE : on remplace l'element d'indice 1
>>> notes
[12, 20, 15, 9]
>>> notes[0:2] # tranche
[12, 20]
Règle 2 — Indices négatifs et tranches
-
Indice négatif : on compte depuis la fin.
t[-1]est le dernier élément,t[-2]l’avant-dernier ;t[-k]désignet[len(t) - k]. -
Tranche
t[a:b]: un nouveau tableau, formé des éléments d’indicesaàb - 1(best exclu, comme dansrange). Siaest omis, on part du début ; sibest omis, on va jusqu’à la fin. -
Les deux se combinent :
t[:-1]est le tableau privé de son dernier élément, c’est-à-diret[0:len(t) - 1].
Tout cela vaut aussi pour les chaînes et les p-uplets.
>>> notes = [12, 20, 15, 9]
>>> notes[-1] # dernier element
9
>>> notes[-2] # avant-dernier
15
>>> notes[1:3] # indices 1 et 2 (3 exclu)
[20, 15]
>>> notes[:2] # depuis le debut
[12, 20]
>>> notes[2:] # jusqu'a la fin
[15, 9]
>>> notes[:-1] # tout sauf le dernier
[12, 20, 15]
Parcourir un tableau (capacité attendue)#
(1) Par élément, quand seules les valeurs comptent :
somme = 0
for note in notes: # note prend chaque valeur
somme = somme + note
(2) Par indice, quand on a besoin de la position ou qu’on veut modifier :
for i in range(len(notes)):
notes[i] = notes[i] + 1 # +1 point a chaque note
Remarque — Pourquoi la méthode 1 ne modifie pas le tableau
Dans for note in notes, la variable note est un nouveau nom qui pointe tour à tour vers chaque élément. Lui réaffecter note = note + 1 le fait pointer ailleurs, sans toucher au tableau. Pour modifier, il faut l’indice (méthode 2). Ces deux parcours deviendront un patron général (somme, recherche, maximum) au chapitre Algorithmique : le parcours séquentiel.
Construction par compréhension (capacité attendue)#
Écriture concise, à maîtriser absolument : elle fabrique un tableau à partir d’un itérable.
Règle 3 — Syntaxe de la compréhension
Deux formes (une par ligne), chaque couleur repérant une partie :
| forme simple : | [ expression(x)forxinitérable ] |
| avec filtre : | [ expression(x)forxinitérableifcondition(x) ] |
expression = ce que l’on range variable = parcourt l’itérable itérable = ce que l’on parcourt condition = filtre (facultatif)
>>> [2 * n for n in range(5)] # les 5 premiers pairs
[0, 2, 4, 6, 8]
>>> [x * x for x in [1, 2, 3, 4]] # les carres
[1, 4, 9, 16]
>>> [n for n in range(20) if n % 3 == 0] # avec filtre
[0, 3, 6, 9, 12, 15, 18]
Pour les curieux (facultatif) — Un premier pas vers la programmation fonctionnelle
Une compréhension est une expression qui construit un nouveau tableau sans modifier quoi que ce soit d’autre : c’est un élément de programmation fonctionnelle, un paradigme (une manière de programmer) que l’on étudiera en Terminale.
Exemple — La compréhension condense une boucle à accumulateur
Les deux codes produisent [1, 4, 9, 16, 25] :
carres = [] # version longue
for k in range(1, 6):
carres.append(k * k)
carres = [k * k for k in range(1, 6)] # version par comprehension
Méthodes des tableaux au-delà du programme#
Un tableau étant mutable, il possède des méthodes (appel avec un point). Deux d’entre elles suffisent cette année, et reviennent dans les sujets de bac.
Règle 4 — Ajouter et retirer en fin de tableau
Un tableau t dispose des méthodes suivantes :
| Appel | Effet |
|---|---|
| t.append(x) | ajoute x à la fin |
| t.pop() | retire et renvoie le dernier élément |
| t.pop(i) | retire et renvoie l’élément d’indice i |
>>> t = [3, 1, 2]
>>> t.append(5) # -> [3, 1, 2, 5]
>>> t.pop() # renvoie 5 ; t -> [3, 1, 2]
5
>>> t.pop(0) # renvoie 3 ; t -> [1, 2]
3
Règle 5 — Modifier sur place vs renvoyer une copie
append modifie le tableau et renvoie None : n’écrivez jamais t = t.append(5) (vous perdriez tout). Pour obtenir un nouveau tableau sans modifier l’original, on le construit, par exemple par concaténation (+).
>>> t = [3, 1, 2]
>>> t + [5] # NOUVEAU tableau
[3, 1, 2, 5]
>>> [0] + t # ajout en tete, NOUVEAU tableau
[0, 3, 1, 2]
>>> t # original intact
[3, 1, 2]
Règle 6 — Méthode : tout le reste s’écrit avec une boucle
Compter les occurrences d’une valeur, chercher sa position, retirer une valeur, inverser ou trier un tableau : on ne cherche pas une méthode toute faite, on écrit le parcours (exercices « Chercher et compter » et « Renverser sans reverse »). Ces algorithmes sont au cœur des chapitres Algorithmique : le parcours séquentiel et Les tris.
Le fil rouge à l’œuvre : références, alias et copie#
Voici le point le plus important — et le plus piégeux — du chapitre. Reprenons le dessin du § I.
Règle 7 — Affecter un tableau ne le copie pas !
b = a ne crée aucun nouvel objet : il fait simplement pointer b vers le même tableau que a. On dit que a et b sont des alias. Modifier via l’un se voit via l’autre.
↺ Retour sur l'activité. C’est la liste de courses de l’activité : Papa et Maman avaient collé deux étiquettes sur la même feuille, et print(maman) affichait [’brioche’, ’lait’, ’pommes’]. Pour que Papa ait sa propre liste, il fallait recopier la feuille : c’est la vraie copie présentée ci-dessous.
>>> a = [1, 2, 3]
>>> b = a # b pointe vers le MEME objet
>>> b[0] = 99
>>> a # a a change aussi !
[99, 2, 3]
Pour une vraie copie (objet indépendant), on reconstruit un tableau :
>>> a = [1, 2, 3]
>>> b = [x for x in a] # (ou a[:]) : NOUVEL objet
>>> b[0] = 99
>>> a # intact
[1, 2, 3]
Remarque — Copie d’un tableau de tableaux
Une copie simple ne duplique que le premier niveau : pour un tableau de tableaux, les sous-tableaux restent partagés. Pour tout dédoubler, il faut aussi recopier chaque sous-tableau (copie profonde) : c’est l’objet de l’exemple suivant.
Exemple — Copier un tableau de tableaux avec deux compréhensions emboîtées
Construire une copie indépendante de grille = [[1, 2], [3, 4]] à l’aide de deux compréhensions emboîtées, puis vérifier que modifier la copie ne touche pas l’original.
Correction
La compréhension intérieure recrée chaque ligne, la compréhension extérieure crée un nouveau tableau de ces lignes : aucun tableau n’est partagé.
>>> grille = [[1, 2], [3, 4]]
>>> copie = [[x for x in ligne] for ligne in grille]
>>> copie[0][0] = 99
>>> copie
[[99, 2], [3, 4]]
>>> grille # original intact
[[1, 2], [3, 4]]
À comparer avec une copie simple [ligne for ligne in grille] : la même modification aurait changé grille en [[99, 2], [3, 4]], car les lignes seraient restées partagées.
▶ Exercices d'application : exercices 6 à 16, 35 et 37 (les tableaux ; les compréhensions)
Tableaux de tableaux : les matrices (capacité attendue)#
Un tableau dont les éléments sont des tableaux de même longueur représente une matrice : un quadrillage de \(n\) lignes et \(p\) colonnes.
M = [[1, 2, 3],
[4, 5, 6]] # 2 lignes, 3 colonnes
Règle 8 — Accès à une case : M[i][j]
M[i] est la ligne d’indice i (un tableau) ; M[i][j] est la case ligne i, colonne j. Le nombre de lignes est len(M), de colonnes len(M[0]).
>>> M[0] # premiere ligne
[1, 2, 3]
>>> M[1][2] # ligne 1, colonne 2
6
On parcourt une matrice avec deux boucles imbriquées :
total = 0
for i in range(len(M)):
for j in range(len(M[0])):
total = total + M[i][j] # somme de toutes les cases
Le fil rouge tranche le débat : [[0]*p]*n est un piège#
Comment créer une grille de zéros ? On serait tenté d’écrire [[0] * p] * n, par exemple [[0] * 3] * 2. Erreur. Le modèle mémoire l’explique d’un coup : l’opérateur * ne copie pas la ligne, il répète la même référence. Les deux lignes sont alors un seul et même tableau — exactement l’alias du § IV.
>>> grille = [[0] * 3] * 2 # PIEGE
>>> grille[0][0] = 1
>>> grille
[[1, 0, 0], [1, 0, 0]] # la 2e ligne a change aussi !
La bonne façon : une compréhension imbriquée, qui crée à chaque tour une ligne distincte.
n, p = 2, 3
grille = [[0 for j in range(p)] for i in range(n)] # 2 lignes INDEPENDANTES
Exemple — Une image est une matrice
Une image en niveaux de gris est une matrice d’entiers de \(0\) (noir) à \(255\) (blanc). La traiter, c’est parcourir cette matrice :
# Negatif : chaque pixel p devient 255 - p
for i in range(len(image)):
for j in range(len(image[0])):
image[i][j] = 255 - image[i][j]
En couleurs, chaque pixel est lui-même un p-uplet (rouge, vert, bleu).
▶ Exercices d'application : exercices 17 à 21 (les matrices)
Le dictionnaire (dict) : l’accès par clé#
Dans un tableau, l’étiquette d’accès est imposée : un indice \(0, 1, 2, \ldots\). Dans un dictionnaire, on la choisit : c’est la clé.
Définition 5 — Dictionnaire
Un dictionnaire (type dict) est un ensemble de couples clé \(\to\) valeur. Les clés sont uniques et immuables (souvent str, int ou tuple). On l’écrit entre accolades, chaque couple sous la forme clé: valeur.
↺ Retour sur l'activité. Les tiroirs étiquetés de l’activité formaient un dictionnaire : le prénom est la clé, le numéro de casier la valeur. Deux tiroirs « Hugo » étaient impossibles, comme deux clés égales dans un dictionnaire.
>>> age = {"Alice": 17, "Bob": 16, "Chloe": 17}
>>> age["Alice"] # acces par la cle, non par un indice
17
>>> vide = {} # dictionnaire vide
Remarque — Tableau associatif = enregistrement
Le nom savant est tableau associatif. C’est l’outil idéal pour une fiche : {"nom": "Ada", "annee": 1815, "domaine": "informatique"}. Au chapitre Les données en tables, une table entière sera une liste de telles fiches.
Ajouter, modifier, supprimer#
Différence majeure avec le tableau : on crée une nouvelle clé par simple affectation (impossible avec un indice de tableau, qui doit déjà exister).
>>> age = {"Alice": 17, "Bob": 16}
>>> age["David"] = 15 # nouvelle cle : creee
>>> age["Bob"] = 17 # cle existante : valeur remplacee
>>> del age["Alice"] # suppression du couple
>>> len(age) # nombre de couples
2
Règle 9 — Le test in porte sur les clés
>>> "Bob" in age # une cle ?
True
>>> 17 in age # NON : in ne regarde pas les valeurs
False
Tester cle in d avant d[cle] évite l’erreur KeyError sur une clé absente.
Itérer sur un dictionnaire (capacité attendue)#
Une boucle for sur un dictionnaire parcourt ses clés. Trois méthodes précisent le parcours.
Règle 10 — keys, values, items
d.keys() : les clés. d.values() : les valeurs. d.items() : les couples (clé, valeur).
age = {"Alice": 17, "Bob": 16, "Chloe": 17}
for prenom in age: # parcourt les cles (defaut)
print(prenom, "a", age[prenom], "ans")
for prenom, a in age.items(): # couples : tres pratique
print(prenom, "a", a, "ans")
total = 0
for a in age.values(): # parcourt les valeurs
total = total + a
moyenne = total / len(age) # moyenne des ages
Exemple — Compter des occurrences : le cas d’école du dictionnaire
Clé = la lettre, valeur = son compteur.
def compter(mot):
compteur = {}
for lettre in mot:
if lettre in compteur:
compteur[lettre] = compteur[lettre] + 1
else:
compteur[lettre] = 1
return compteur
compter("abracadabra") # {'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1}
Construction par compréhension au-delà du programme#
>>> {n: n * n for n in range(1, 5)}
{1: 1, 2: 4, 3: 9, 4: 16}
Exemple — Chiffre de César via un dictionnaire de correspondance
Décalage de \(3\) rangs ; ord/chr convertissent lettre \(\leftrightarrow\) code (’A’ \(\leftrightarrow 65\)).
decalage = {chr(65 + i): chr(65 + (i + 3) % 26) for i in range(26)}
# decalage['A'] = 'D' , decalage['X'] = 'A' , ...
code = ""
for c in "BONJOUR":
code = code + decalage[c] # code vaut "ERQMRXU"
Le fil rouge, une dernière fois : pourquoi la clé est-elle immuable ?#
Règle 11 — Une clé de dictionnaire doit être immuable
Un tableau ne peut pas être une clé ; un p-uplet, si. Le modèle mémoire l’explique : le dictionnaire range chaque valeur à une place calculée à partir de la clé. Si la clé pouvait changer après coup (comme un tableau mutable), cette place ne correspondrait plus à rien et la valeur serait introuvable. D’où l’exigence d’une clé figée.
Pour les curieux (facultatif) — Copier un dictionnaire
Comme pour les tableaux, d2 = d crée un alias, pas une copie. Pour obtenir un nouveau dictionnaire contenant les mêmes couples clé-valeur, on le reconstruit par compréhension : d2 = {cle: d[cle] for cle in d}.
Exemple — Clés composées avec des p-uplets
Comme un p-uplet est immuable, il fait une clé parfaite pour une grille creuse ou un planning. Hôtel, clé (chambre, jour) \(\to\) client :
reservations = {}
reservations[(12, "lundi")] = "Alice"
reservations[(12, "mardi")] = "Bob"
# "Chambre 12 le mardi ?" -> reservations[(12, "mardi")] vaut "Bob"
▶ Exercices d'application : exercices 22 à 30 et 36 (les dictionnaires ; le fil rouge alias/copie)
Un peu d’histoire, et pour aller plus loin#
Pour les curieux (facultatif) — Aux origines du tableau associatif
Accéder à une donnée par une clé plutôt que par une position repose sur le hachage (hashing), inventé en 1953 chez IBM par Hans Peter Luhn : une fonction transforme la clé en une adresse mémoire, rendant l’accès quasi instantané — et exigeant, on l’a vu, une clé figée (« hachable »). Les tableaux, eux, sont aussi anciens que les premiers ordinateurs : ranger des valeurs dans des cases mémoire contiguës et numérotées est au cœur de l’architecture de von Neumann (1945).
Pour les curieux (facultatif) — Ces types sont partout
Le format JSON, qui fait circuler la quasi-totalité des données du Web, n’est que des tableaux et des dictionnaires emboîtés. En calcul scientifique, la bibliothèque NumPy fournit de vrais tableaux à \(n\) dimensions, bien plus rapides que les list sur de gros volumes.
Pour les curieux (facultatif) — Liens avec d’autres chapitres
-
Ce qu’il réutilise. Les chaînes et les boucles des Bases de la programmation Python ; le modèle provisoire du casier y est remplacé par celui de l’étiquette et de la flèche.
-
Ce qu’il prépare. Les tableaux seront la matière première de l’année (parcours, tris, dichotomie) ; une table de données sera une liste de dictionnaires.
-
En Terminale. Structures linéaires et Programmation objet présenteront d’autres façons de ranger des données ; les dictionnaires représenteront les graphes, et Diviser pour régner fera tourner une image stockée dans une matrice.
Bilan — la carte mémoire#
| Notion | À retenir |
|---|---|
p-uplet ( ) |
ordonné, immuable ; sert à renvoyer plusieurs valeurs, à faire une clé |
tableau [ ] |
ordonné, mutable ; lecture et modification par indice |
dictionnaire { } |
couples clé \(\to\) valeur ; in teste les clés ; keys/values/items |
| Les 2 questions | accès par indice ou par clé ? modifiable ou figé ? |
| Compréhension | [expr(x) for x in ... if ...] : construit un tableau en une ligne |
| Fil rouge (référence) | une variable est une flèche vers un objet |
| Alias vs copie | b = a \(\to\) même objet ; [x for x in a] / a[:] \(\to\) vraie copie |
| Piège des matrices | [[0]*p]*n partage une seule ligne ; utiliser une compréhension |
| Clé de dictionnaire | doit être immuable : p-uplet oui, tableau non |
Retour à la situation de départ
-
Dans un tableau (
list) :notes = [12, 8, 15, ...]; chaque note se lit et se modifie par son indice,notes[i], à partir de 0 (§ IV). -
Avec un dictionnaire :
casiers = {"Léa": 112, "Hugo": 87}, puiscasiers["Hugo"]donne87; on accède par la clé, non par une position (§ VI). -
copie = notesne crée aucun objet : les deux noms sont des alias du même tableau. Pour une vraie copie, on reconstruit le tableau :copie = [x for x in notes](§ IV).
Erreurs fréquentes#
-
Croire que
b = acopie la liste. On crée une deuxième étiquette sur la même liste : modifierbmodifiea. Le réflexe : pour copier, une compréhension[x for x in a](oua[:]). -
Le piège
[[0]*p]*n. Lesnlignes sont la même liste partagée. Le réflexe :[[0]*p for i in range(n)]. -
Vouloir modifier un p-uplet. Un
tupleest immuable ; une liste est mutable. -
Clé de dictionnaire mutable. Une clé doit être immuable (un p-uplet oui, une liste non).
-
Confondre indice et clé. On accède à une liste par indice (\(0, 1, 2\dots\)), à un dictionnaire par clé.
-
Modifier une liste pendant qu’on la parcourt (ajout / suppression) : résultats imprévisibles.
Savoir-faire à maîtriser#
À la fin du chapitre, je sais…
-
créer et manipuler p-uplets, listes (tableaux) et dictionnaires ;
-
accéder par indice / par clé, et parcourir une structure ;
-
construire une matrice (tableau de tableaux) sans le piège du partage ;
-
écrire une compréhension de liste ;
-
comprendre mutabilité et aliasing (modèle mémoire) et copier proprement ;
-
choisir la bonne structure (indice / clé, mutable / immuable).