11 - Tuples
Introduction
Les tuples (ou n-uplets en français) sont des séquences immutables : on ne peut pas les modifier après leur création. Cette propriété les distingue des listes, qui sont, elles, modifiables.
Le programme de NSI emploie le mot p-uplet : un tuple de p éléments est un p-uplet. Quand les éléments sont repérés par un nom plutôt que par leur position, on parle de p-uplet nommé ; en Python, on le représente par un dictionnaire (chapitre 12).
En mathématiques, on parle de couple pour deux éléments, de triplet pour trois, de quadruplet pour quatre, etc. En informatique, le terme tuple désigne de façon générique un n-uplet, c’est-à-dire une séquence ordonnée de \(n\) éléments.
Création d’un tuple
On crée un tuple en plaçant ses éléments entre parenthèses, séparés par des virgules :
T = ('a', 'b', 'c')
print(T, 'est de type', type(T))
('a', 'b', 'c') est de type <class 'tuple'>
Les parenthèses sont en réalité facultatives : c’est la virgule qui fait le tuple.
T = 'a', 'b', 'c'
print(T, 'est de type', type(T))
('a', 'b', 'c') est de type <class 'tuple'>
On peut aussi créer un tuple à partir d’une autre séquence grâce à la fonction tuple()
:
T = tuple(['a', 'b', 'c']) # à partir d'une liste
print(T, 'est de type', type(T))
('a', 'b', 'c') est de type <class 'tuple'>
Piège classique : le tuple à un seul élément
Attention à la syntaxe pour créer un tuple contenant un seul élément. Les parenthèses seules ne suffisent pas : il faut ajouter une virgule après l’élément.
T = ('a') # ceci n'est PAS un tuple, mais une chaîne
print(T, 'est de type', type(T))
T = ('a',) # ceci EST un tuple (remarquez la virgule)
print(T, 'est de type', type(T))
a est de type <class 'str'>
('a',) est de type <class 'tuple'>
À retenir. C’est la virgule qui crée le tuple, pas les parenthèses. Cependant, on préfère toujours utiliser les parenthèses pour la lisibilité.
Le tuple vide
On crée un tuple vide avec des parenthèses vides ou avec tuple() sans argument :
T_vide = ()
print(T_vide, 'est de type', type(T_vide), 'et de longueur', len(T_vide))
() est de type <class 'tuple'> et de longueur 0
Accès aux éléments
On accède aux éléments d’un tuple exactement comme pour une liste, par leur indice (en commençant à 0) :
T = ('a', 'b', 'c', 'd', 'e')
print(T[0]) # premier élément
print(T[2]) # troisième élément
print(T[-1]) # dernier élément
a
c
e
Le slicing fonctionne aussi comme pour les listes :
T = ('a', 'b', 'c', 'd', 'e')
print(T[1:4]) # du deuxième au quatrième
print(T[:3]) # les trois premiers
print(T[::2]) # un élément sur deux
('b', 'c', 'd')
('a', 'b', 'c')
('a', 'c', 'e')
Immutabilité
La caractéristique fondamentale d’un tuple est qu’on ne peut pas modifier ses éléments après sa création. Toute tentative de modification provoque une erreur :
T = ('a', 'b', 'c')
print(T[1]) # on peut lire un élément
b
# Cette instruction génère une erreur
T[1] = 'z' # on ne peut PAS modifier un élément
TypeError: 'tuple' object does not support item assignment
Pourquoi est-ce utile ? L’immutabilité offre plusieurs avantages :
- sécurité : on est garanti que les données ne seront pas modifiées accidentellement ;
- clé de dictionnaire : les tuples peuvent servir de clés dans un dictionnaire, contrairement aux listes (car les clés doivent être immutables).
Exemple concret : pour stocker les cases d’un plateau de jeu, on peut utiliser les coordonnées (ligne, colonne) comme clés d’un dictionnaire :
plateau = {}
plateau[(0, 0)] = "tour"
plateau[(0, 1)] = "cavalier"
plateau[(3, 4)] = "pion"
print(plateau[(0, 0)])
tour
Ceci ne serait pas possible avec des listes [0, 0] car les listes ne peuvent pas être clés de dictionnaire.
Conversion entre listes et tuples
On peut facilement passer d’un type à l’autre grâce aux fonctions tuple() et list() :
L = [1, 2, 3, 'toto']
T = tuple(L)
print('Liste :', L, '-> Tuple :', T)
chaine = 'azerty'
T2 = tuple(chaine)
print('Chaîne :', chaine, '-> Tuple :', T2)
T3 = (10, 20, 30)
L2 = list(T3)
print('Tuple :', T3, '-> Liste :', L2)
Liste : [1, 2, 3, 'toto'] -> Tuple : (1, 2, 3, 'toto')
Chaîne : azerty -> Tuple : ('a', 'z', 'e', 'r', 't', 'y')
Tuple : (10, 20, 30) -> Liste : [10, 20, 30]
Manipulation des tuples
Même si les tuples sont immutables, on peut construire de nouveaux tuples par concaténation et multiplication :
T1 = ('a', 'b', 'c')
T2 = ('d', 'e')
print('T1 + T2 =', T1 + T2)
print('T2 * 3 =', T2 * 3)
T1 + T2 = ('a', 'b', 'c', 'd', 'e')
T2 * 3 = ('d', 'e', 'd', 'e', 'd', 'e')
On peut aussi vérifier l’appartenance d’un élément avec le mot-clé in et connaître la longueur avec len() :
T = ('pomme', 'banane', 'cerise')
print('banane' in T)
print('kiwi' in T)
print('Longueur :', len(T))
True
False
Longueur : 3
Les fonctions min(), max() et sum() fonctionnent également sur les tuples (à condition que les éléments soient comparables ou numériques) :
notes = (12, 15, 8, 17, 14)
print('Min :', min(notes))
print('Max :', max(notes))
print('Somme :', sum(notes))
print('Moyenne :', sum(notes) / len(notes))
Min : 8
Max : 17
Somme : 66
Moyenne : 13.2
Déballage de tuples
Le déballage (ou unpacking) permet d’affecter chaque élément d’un tuple à une variable distincte en une seule instruction :
coordonnees = (3, 7)
x, y = coordonnees
print(f"x = {x}, y = {y}")
x = 3, y = 7
C’est grâce à cette mécanique que l’on peut échanger deux variables en une seule ligne en Python :
a, b = 5, 10
print(f"Avant : a = {a}, b = {b}")
a, b = b, a
print(f"Après : a = {a}, b = {b}")
Avant : a = 5, b = 10
Après : a = 10, b = 5
Attention. Le nombre de variables à gauche doit correspondre exactement au nombre d’éléments du tuple, sinon Python lève une erreur :
T = (1, 2, 3)
a, b = T # erreur : 3 éléments mais seulement 2 variables
ValueError: too many values to unpack (expected 2)
Tuples et fonctions
Les tuples sont très utilisés pour qu’une fonction renvoie plusieurs valeurs :
def min_max(L):
"""Renvoie le minimum et le maximum d'une liste."""
return (min(L), max(L))
resultat = min_max([4, 7, 2, 9, 1])
print(resultat)
# Avec le déballage :
petit, grand = min_max([4, 7, 2, 9, 1])
print(f"Le plus petit est {petit}, le plus grand est {grand}")
(1, 9)
Le plus petit est 1, le plus grand est 9
Tuple nommé (pour aller plus loin)
Le module collections propose les namedtuple, qui permettent d’accéder aux éléments par un nom plutôt que par un indice :
from collections import namedtuple
Eleve = namedtuple('Eleve', ['nom', 'prenom', 'classe'])
e = Eleve('Dupont', 'Marie', '1NSI')
print(e.nom, e.prenom, e.classe)
print(e[0]) # l'accès par indice fonctionne toujours
Dupont Marie 1NSI
Dupont
Résumé : tuples vs listes
| Caractéristique | Liste | Tuple |
|---|---|---|
| Syntaxe | [1, 2, 3] | (1, 2, 3) |
| Modifiable | Oui (muable) | Non (immutable) |
| Clé de dictionnaire | Non | Oui |
| Cas d’usage | Collection évolutive | Données fixes |