Les types construits
Cours · NSI (première), chapitre 4 · première, spécialité numérique et sciences informatiques · le début du chapitre, la suite sur Adloun
Les types vus jusqu'ici — entiers, flottants, booléens, chaînes — ont un point commun : une valeur, une donnée. Or les problèmes intéressants portent sur des collections : les notes d'une classe, les pixels d'une image, les coordonnées d'un point, les lignes d'un fichier. Il faut donc des types qui construisent de nouvelles valeurs à partir des valeurs de base. Le programme en présente trois, « au fur et à mesure qu'ils sont nécessaires » : les p-uplets, les tableaux, les dictionnaires. Ce chapitre traite les deux premiers ; le suivant est consacré aux dictionnaires.
Hors programme : Le vocabulaire de Python n'est pas celui de tout le monde
Le programme prévient : « en pratique, on utilise les appellations de Python, qui peuvent être différentes de celles d'autres langages ». Ce que ce chapitre appelle tableau s'écrit en Python avec le type list — le programme note d'ailleurs que « Python identifie listes et tableaux ». Dans d'autres langages, liste et tableau désignent deux structures très différentes, aux coûts opposés. Retenez la notion, pas seulement le mot.
4.1 Les p-uplets
4.1.1 Définition
Un p-uplet (en anglais tuple) est une suite finie et ordonnée de valeurs, éventuellement de types différents. On le note entre parenthèses, les composantes séparées par des virgules.
point = (3, 7) # un couple d'entiers
eleve = ("Nour", 17, 15.5) # un triplet : chaîne, entier, flottant
Deux traits le caractérisent, et les deux comptent :
- l'ordre est significatif : et sont deux p-uplets différents ;
- on ne le modifie pas : une fois construit, un p-uplet ne change plus. Écrire
point[0] = 5provoque une erreur.
Cette dernière propriété n'est pas une gêne, c'est une garantie. Un p-uplet sert à représenter une valeur composite dont les composantes forment un tout — des coordonnées, un résultat à deux volets — et qu'on remplace en bloc plutôt que par morceaux. Pour une collection qu'on veut modifier élément par élément, on emploie un tableau : c'est l'objet de la section suivante.
4.1.2 Renvoyer plusieurs valeurs à la fois
Capacité attendue
« Écrire une fonction renvoyant un p-uplet de valeurs. »
C'est l'usage principal du p-uplet. Une fonction ne renvoie qu'une seule valeur — mais si cette valeur est un p-uplet, elle en renvoie autant qu'on veut.
def division_euclidienne(a, b):
"""Quotient et reste de la division euclidienne de a par b.
Précondition : b > 0.
Postcondition : a == b * q + r et 0 <= r < b.
"""
assert b > 0, "le diviseur doit etre strictement positif"
q = a // b
r = a - b * q
assert a == b * q + r and 0 <= r < b
return q, r
On serait tenté d'écrire assert b != 0 : c'est insuffisant. Pour , la division entière de Python arrondit vers le bas et le reste devient négatif — la postcondition n'a alors plus de sens. Une précondition trop large laisse passer des appels que la fonction ne sait pas honorer. Exiger n'est pas une restriction arbitraire : c'est le domaine où la promesse tient.
Côté appelant, on récupère les composantes d'un coup — c'est l'affectation multiple, ou déballage :
q, r = division_euclidienne(17, 5) # q vaut 3, r vaut 2
Méthode : Échanger deux variables
L'affectation multiple donne l'échange le plus court qui soit :
a, b = b, a
Le membre de droite est évalué entièrement avant la moindre affectation : c'est le p-uplet qui est construit, puis déballé. Aucune variable temporaire n'est nécessaire, et l'ordre n'a pas d'importance. Nous nous en servirons à chaque tri du chapitre 7.
4.1.3 Les p-uplets nommés
Le triplet ("Nour", 17, 15.5) pose un problème dès qu'il circule : rien ne dit ce que sont et . Un âge ? un rang ? une moyenne ? Il faut lire le code qui l'a produit pour le savoir — et ce code changera.
Un p-uplet nommé est un p-uplet dont chaque composante porte un nom de champ. On accède aux composantes par leur nom plutôt que par leur rang.
from collections import namedtuple
Eleve = namedtuple("Eleve", ["nom", "age", "moyenne"])
nour = Eleve("Nour", 17, 15.5)
nour.moyenne # 15.5 — sans équivoque
nour[2] # 15.5 également : un p-uplet nommé reste un p-uplet
Le gain n'est pas cosmétique. nour.moyenne reste juste si l'on insère un champ au milieu ; nour[2] devient faux silencieusement. Nommer, c'est se protéger d'une classe entière d'erreurs — celles qui ne provoquent aucun message.
Exercices du chapitre
- Écrire une fonction min max(t) renvoyant le couple (plus petit… corrigé
- La suite de Fibonacci s'écrit en une ligne grâce à l'affectation… corrigé
- Un tableau de points du plan se représente naturellement par un… corrigé
- Écrire moyenne glissante(t, k) , qui renvoie les moyennes de toutes… corrigé
- Écrire couples(t), qui renvoie le tableau de tous les couples avec corrigé
- Écrire indices des(t, v) , qui renvoie le tableau de tous les indices… corrigé