14  Les tuples

Les tuples ressemblent beaucoup aux listes… avec une différence fondamentale : ils sont immuables. Cette particularité leur donne des usages spécifiques : retours multiples de fonction, données constantes, clés de dictionnaire. Le TOSA teste surtout les différences avec les listes.

14.1 Qu’est-ce qu’un tuple ?

Un tuple est une séquence ordonnée et immuable d’éléments, pouvant être de types différents.

coordonnees = (48.85, 2.35)       # latitude, longitude
rgb = (255, 128, 0)                # rouge, vert, bleu
personne = ("Alice", 30, "Paris")
vide = ()

print(coordonnees, type(coordonnees))
(48.85, 2.35) <class 'tuple'>

Les quatre caractéristiques :

  1. Ordonnés : chaque élément a une position fixe.
  2. Immuables : on ne peut pas ajouter, retirer, changer.
  3. Indexés à partir de 0.
  4. Hétérogènes : mélange de types autorisé.

Créer un tuple

On utilise des parenthèses () ou juste des virgules :

t1 = (1, 2, 3)
t2 = 1, 2, 3               # les parenthèses sont facultatives !
t3 = tuple([1, 2, 3])      # depuis une liste

print(t1)
print(t2)
print(t3)
print(t1 == t2 == t3)
(1, 2, 3)
(1, 2, 3)
(1, 2, 3)
True

Tuple à un seul élément — attention !

⚠️ Piège TOSA incontournable : la virgule du singleton

Pour créer un tuple d’un seul élément, il faut impérativement une virgule après.

# Sans virgule : ce n'est PAS un tuple, mais la valeur entre parenthèses
pas_tuple = (42)
print(pas_tuple, type(pas_tuple))     # int !

# Avec virgule : VRAI tuple
singleton = (42,)
print(singleton, type(singleton))     # tuple

# Même sans parenthèses, la virgule suffit
autre = 42,
print(autre, type(autre))
42 <class 'int'>
(42,) <class 'tuple'>
(42,) <class 'tuple'>

Question TOSA type : « Que vaut type((5)) ? » → int (piège !).

14.2 Accès et lecture : comme une liste

On accède aux éléments par indice, on peut faire du slicing, tout comme les listes.

personne = ("Alice", 30, "Paris")

print(personne[0])       # "Alice"
print(personne[-1])      # "Paris"
print(personne[0:2])     # ("Alice", 30)
print(len(personne))     # 3
print("Alice" in personne)   # True
Alice
Paris
('Alice', 30)
3
True

14.3 On ne peut PAS modifier un tuple

C’est la différence fondamentale avec une liste.

couleurs = ("rouge", "vert", "bleu")
couleurs[0] = "jaune"
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[5], line 2
      1 couleurs = ("rouge", "vert", "bleu")
----> 2 couleurs[0] = "jaune"

TypeError: 'tuple' object does not support item assignment

Pas d’append, pas de remove, pas de réaffectation d’élément. Seules opérations permises : lecture, concaténation avec + (crée un nouveau tuple), répétition avec *, slicing (crée un nouveau tuple).

t1 = (1, 2, 3)
t2 = (4, 5)

# Concaténation → nouveau tuple
t3 = t1 + t2
print(t3)

# Répétition → nouveau tuple
t4 = t1 * 2
print(t4)

# Slicing → nouveau tuple
t5 = t1[:2]
print(t5)
(1, 2, 3, 4, 5)
(1, 2, 3, 1, 2, 3)
(1, 2)
L’immuabilité ne cascade pas

Un tuple ne peut pas changer de structure. Mais si un de ses éléments est une liste (qui est mutable), cette liste peut être modifiée :

t = (1, 2, [10, 20])
t[2].append(30)       # on modifie la LISTE interne, pas le tuple
print(t)
(1, 2, [10, 20, 30])

On ne peut pas faire t[2] = [100] (réassignation), mais on peut modifier le contenu de la liste interne. C’est un point fin.

14.4 Déballage (unpacking)

Le déballage permet d’affecter plusieurs variables en une seule ligne, dans l’ordre du tuple.

point = (3, 5)
x, y = point              # unpacking
print("x =", x, "| y =", y)
x = 3 | y = 5

Ça fonctionne aussi avec une liste :

nom, age, ville = ["Alice", 30, "Paris"]
print(nom, age, ville)
Alice 30 Paris

Échanger deux variables

Un idiome très Pythonique que le TOSA adore :

a, b = 10, 20
print("Avant :", a, b)

a, b = b, a               # échange en une ligne !
print("Après :", a, b)
Avant : 10 20
Après : 20 10

Sans ça, il faudrait une variable temporaire :

# Version classique (autres langages)
temp = a
a = b
b = temp

Déballage avec * (bonus)

Le * permet de récupérer “tout le reste” dans une variable.

nombres = (1, 2, 3, 4, 5)

premier, *milieu, dernier = nombres
print("premier :", premier)
print("milieu  :", milieu)       # list (pas tuple !)
print("dernier :", dernier)
premier : 1
milieu  : [2, 3, 4]
dernier : 5

14.5 Les méthodes des tuples

Les tuples étant immuables, ils ont très peu de méthodes (seulement 2, contre ~10 pour les listes) :

Méthode Effet
count(x) Nombre d’occurrences de x
index(x) Indice de la 1ère occurrence
t = (1, 2, 3, 2, 4, 2)
print(t.count(2))     # 3
print(t.index(3))     # 2
3
2

14.6 Pourquoi utiliser un tuple plutôt qu’une liste ?

Bonne question ! Voici les cas typiques :

1. Représenter des données immuables par nature

Coordonnées géographiques, couleur RGB, date → ces données ne changent pas. Un tuple exprime cette immuabilité.

# ✅ Tuple : l'immuabilité a du sens
paris = (48.85, 2.35)
rouge = (255, 0, 0)

# ❌ Liste : pourquoi serait-elle modifiable ?
paris_liste = [48.85, 2.35]

2. Retour multiple d’une fonction

Les fonctions Python renvoient souvent un tuple quand il y a plusieurs valeurs à retourner.

def min_max(liste):
    return min(liste), max(liste)       # renvoie un tuple

resultat = min_max([3, 1, 4, 1, 5, 9, 2, 6])
print(resultat, type(resultat))

# Déballage immédiat très courant
petit, grand = min_max([3, 1, 4, 1, 5, 9, 2, 6])
print("Min:", petit, "| Max:", grand)
(1, 9) <class 'tuple'>
Min: 1 | Max: 9

3. Clés de dictionnaire

Un dictionnaire (chapitre 7) ne peut avoir comme clés que des objets immuables. Les tuples peuvent servir de clés, pas les listes.

# ✅ Tuple comme clé
scores = {
    ("Alice", "Maths"): 15,
    ("Alice", "Physique"): 14,
    ("Bob", "Maths"): 12,
}
print(scores[("Alice", "Maths")])
15
# ❌ Liste ne peut PAS être clé
d = {[1, 2]: "oups"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[16], line 2
      1 # ❌ Liste ne peut PAS être clé
----> 2 d = {[1, 2]: "oups"}

TypeError: unhashable type: 'list'

4. Performance (marginal)

Les tuples sont légèrement plus rapides et consomment un peu moins de mémoire que les listes. Négligeable la plupart du temps, mais utile sur de très grandes structures.

14.7 Tuple vs liste : tableau récapitulatif

Caractéristique Liste [] Tuple ()
Ordonné
Indexable
Hétérogène
Modifiable
Nombre de méthodes ~10 2
Peut être clé de dict
Syntaxe de création [1, 2, 3] (1, 2, 3) ou 1, 2, 3
Performance Normale Légèrement meilleure

🧩 Quiz 5.1 — Les tuples

Question 1

Quelle est la différence principale entre une liste et un tuple ?

  1. Les listes contiennent des nombres, les tuples des chaînes
  2. Les tuples sont plus grands en mémoire
  3. Les listes sont modifiables, les tuples non
  4. Les tuples n’ont pas d’indice

c) Les listes sont modifiables, les tuples non — c’est la différence fondamentale. Les tuples sont immuables : on ne peut ni ajouter, ni retirer, ni changer d’élément.

Question 2

Que vaut type((5)) ?

  1. tuple
  2. int
  3. list
  4. set

b) int — piège fréquent ! Sans virgule, les parenthèses sont juste des parenthèses de priorité. Pour un tuple d’un élément, il faut (5,).

print(type((5)))         # int
print(type((5,)))        # tuple
print(type(()))          # tuple (vide)
<class 'int'>
<class 'tuple'>
<class 'tuple'>

Question 3

Quelle opération est impossible sur un tuple t = (1, 2, 3) ?

  1. t[0]
  2. t + (4, 5)
  3. t[0] = 10
  4. len(t)

c) t[0] = 10 — modification interdite (immutabilité). Les autres opérations fonctionnent :

  • t[0] : lecture, OK.
  • t + (4, 5) : crée un NOUVEAU tuple (pas de modification de t).
  • len(t) : lecture, OK.

Question 4

Que s’affiche-t-il ?

a, b, c = (1, 2, 3)
print(b)
  1. 1
  2. 2
  3. 3
  4. (1, 2, 3)

b) 2 — déballage du tuple : a=1, b=2, c=3.

a, b, c = (1, 2, 3)
print(b)
2

Question 5

Que fait ce code ?

x, y = 10, 20
x, y = y, x
  1. Lève une erreur
  2. Échange les valeurs de x et y
  3. Met x=20 et y=20
  4. Met x=10 et y=10

b) Échange les valeurs — Python crée d’abord le tuple (y, x) = (20, 10) à droite, puis le déballe dans x, y à gauche. C’est l’idiome Python pour l’échange.

x, y = 10, 20
x, y = y, x
print(x, y)
20 10

Question 6

Que renvoie une fonction qui contient return 1, 2, 3 ?

  1. Une erreur (pas de parenthèses)
  2. Un entier
  3. Un tuple (1, 2, 3)
  4. Une liste [1, 2, 3]

c) Un tuple (1, 2, 3) — les parenthèses sont facultatives. return 1, 2, 3 équivaut à return (1, 2, 3).

def triple():
    return 1, 2, 3

r = triple()
print(r, type(r))
(1, 2, 3) <class 'tuple'>

Question 7

Peut-on utiliser un tuple comme clé d’un dictionnaire ?

  1. Non jamais
  2. Oui toujours
  3. Oui, sauf s’il contient une liste
  4. Oui, uniquement si tous les éléments sont des nombres

c) Oui, sauf s’il contient une liste — les clés de dict doivent être hashables (donc immuables récursivement). Un tuple contenant une liste n’est pas hashable.

d = {([1, 2], "a"): "oups"}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[21], line 1
----> 1 d = {([1, 2], "a"): "oups"}

TypeError: unhashable type: 'list'
# Tuples de valeurs immuables : OK
d = {("a", 1): "valeur", (2, 3): "autre"}
print(d)
{('a', 1): 'valeur', (2, 3): 'autre'}

✏️ Exercice 6.1 — Coordonnées géographiques

Voici une liste de coordonnées de villes sous forme de tuples :

villes = [
    ("Paris", 48.85, 2.35),
    ("Lyon", 45.76, 4.83),
    ("Marseille", 43.30, 5.37),
]

Écrivez un programme qui affiche pour chaque ville : son nom, sa latitude et sa longitude dans une phrase de la forme : Paris : latitude 48.85, longitude 2.35

villes = [
    ("Paris", 48.85, 2.35),
    ("Lyon", 45.76, 4.83),
    ("Marseille", 43.30, 5.37),
]

# Parcourir et afficher chaque ville
villes = [
    ("Paris", 48.85, 2.35),
    ("Lyon", 45.76, 4.83),
    ("Marseille", 43.30, 5.37),
]

for ville in villes:
    nom, lat, lon = ville
    print(f"{nom} : latitude {lat}, longitude {lon}")
Paris : latitude 48.85, longitude 2.35
Lyon : latitude 45.76, longitude 4.83
Marseille : latitude 43.3, longitude 5.37

Plus idiomatique et plus concis :

villes = [
    ("Paris", 48.85, 2.35),
    ("Lyon", 45.76, 4.83),
    ("Marseille", 43.30, 5.37),
]

for nom, lat, lon in villes:         # déballage dans la boucle
    print(f"{nom} : latitude {lat}, longitude {lon}")
Paris : latitude 48.85, longitude 2.35
Lyon : latitude 45.76, longitude 4.83
Marseille : latitude 43.3, longitude 5.37

✏️ Exercice 6.2 — Min et max en un seul appel

Écrivez une fonction extremes(liste) qui renvoie un tuple (min, max) contenant le plus petit et le plus grand élément d’une liste.

def extremes(liste):
    ...
    return ...

petit, grand = extremes([3, 1, 4, 1, 5, 9, 2, 6])
print("Min =", petit, "| Max =", grand)
def extremes(liste):
    return min(liste), max(liste)     # tuple implicite

petit, grand = extremes([3, 1, 4, 1, 5, 9, 2, 6])
print("Min =", petit, "| Max =", grand)
Min = 1 | Max = 9
def extremes_manuel(liste):
    petit = liste[0]
    grand = liste[0]
    for x in liste[1:]:
        if x < petit:
            petit = x
        if x > grand:
            grand = x
    return petit, grand

print(extremes_manuel([3, 1, 4, 1, 5, 9, 2, 6]))
(1, 9)

✏️ Exercice 6.3 — Échange sans variable temporaire

Une personne vous montre ce code ancien :

a = 10
b = 20
temp = a
a = b
b = temp

Réécrivez-le en une seule ligne avec la syntaxe Pythonique.

a = 10
b = 20

# Échanger sans variable intermédiaire, en une seule ligne
...

print(a, b)
a = 10
b = 20

a, b = b, a       # en une ligne, grâce au tuple implicite

print(a, b)
20 10

Ce qui se passe réellement en coulisses :

  1. Python évalue le côté droit : b, a → crée le tuple (20, 10).
  2. Puis il déballe ce tuple vers le côté gauche : a = 20, b = 10.

Cet idiome fonctionne pour plus de 2 variables :

a, b, c = 1, 2, 3
a, b, c = c, a, b      # rotation
print(a, b, c)         # 3, 1, 2
3 1 2

À retenir

Points clés du chapitre
  1. Un tuple est une séquence immuable : (1, 2, 3) — on ne peut rien ajouter/retirer/modifier.
  2. Attention au singleton : (5) est un int, (5,) est un tuple.
  3. Accès, slicing, len, in : comme une liste.
  4. Seulement 2 méthodes : count() et index().
  5. Unpacking : a, b = tuple_de_deux — très courant en Python.
  6. Échange Pythonique : a, b = b, a.
  7. Retour multiple d’une fonction : return x, y renvoie un tuple.
  8. Un tuple peut être clé de dictionnaire (si ses éléments sont eux-mêmes immuables).

← Chapitre précédent : Les listesChapitre suivant : Les dictionnaires →