Définition de l'unpacking en Python
L'unpacking (ou déballage en français) est une fonctionnalité fondamentale de Python qui permet d'extraire les éléments d'un itérable (comme un tuple, une list, un sets ou un dict) et de les assigner simultanément à plusieurs variables en une seule instruction. C'est l'une des techniques les plus élégantes du langage, et elle est omniprésente dans le code Python professionnel.
Si vous souhaitez approfondir cette notion et bien d'autres concepts essentiels, notre formation complète sur Python vous guidera pas à pas dans votre apprentissage.
Au lieu d'accéder manuellement à chaque élément par son index, l'unpacking vous permet d'écrire un code plus concis, plus lisible et plus pythonique. Voyons ensemble comment cette technique fonctionne en détail.
L'unpacking de base : tuples et listes
Unpacking d'un tuple
La forme la plus courante de l'unpacking consiste à assigner les éléments d'un tuple à des variables distinctes :
# Unpacking d'un tuple
coordonnees = (48.8566, 2.3522)
latitude, longitude = coordonnees
print(latitude) # 48.8566
print(longitude) # 2.3522Sans l'unpacking, vous devriez écrire :
# Sans unpacking (moins élégant)
coordonnees = (48.8566, 2.3522)
latitude = coordonnees[0]
longitude = coordonnees[1]La différence est notable : l'unpacking rend le code bien plus lisible et expressif.
Unpacking d'une liste
L'unpacking fonctionne exactement de la même manière avec les list :
# Unpacking d'une liste
couleurs = ["rouge", "vert", "bleu"]
premiere, deuxieme, troisieme = couleurs
print(premiere) # rouge
print(deuxieme) # vert
print(troisieme) # bleuLe nombre de variables à gauche du signe = doit correspondre exactement au nombre d'éléments de l'itérable, sauf si vous utilisez l'opérateur * (que nous verrons plus bas). Sinon, Python lèvera une erreur ValueError.
Échange de variables
L'unpacking permet une astuce célèbre en Python : l'échange de deux variables sans variable temporaire :
# Échange de variables grâce à l'unpacking
a = 10
b = 20
a, b = b, a
print(a) # 20
print(b) # 10Dans beaucoup d'autres langages, cette opération nécessiterait une variable temporaire intermédiaire. En Python, l'unpacking rend cette opération triviale.
L'unpacking étendu avec l'opérateur *
Depuis Python 3, l'opérateur * (parfois appelé opérateur "splat" ou "star") permet de capturer un nombre variable d'éléments lors de l'unpacking. C'est ce qu'on appelle l'unpacking étendu (extended unpacking).
Capturer le début et la fin
# Capturer le premier élément et le reste
notes = [18, 15, 12, 9, 14, 16]
premiere, *reste = notes
print(premiere) # 18
print(reste) # [15, 12, 9, 14, 16]# Capturer le dernier élément
notes = [18, 15, 12, 9, 14, 16]
*debut, derniere = notes
print(debut) # [18, 15, 12, 9, 14]
print(derniere) # 16
Capturer le milieu
# Capturer le premier, le dernier et le milieu
notes = [18, 15, 12, 9, 14, 16]
premiere, *milieu, derniere = notes
print(premiere) # 18
print(milieu) # [15, 12, 9, 14]
print(derniere) # 16La variable précédée de * sera toujours de type list, même si elle ne contient qu'un seul élément ou aucun élément (liste vide).
Ignorer des valeurs avec _
La convention en Python est d'utiliser le caractère _ (underscore) pour ignorer des valeurs dont vous n'avez pas besoin :
# Ignorer certaines valeurs
nom, _, age, _ = ("Alice", "Dupont", 30, "Paris")
print(nom) # Alice
print(age) # 30
# Ignorer plusieurs valeurs avec *_
premier, *_, dernier = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(premier) # 1
print(dernier) # 10
Unpacking de dictionnaires
L'unpacking de dict a ses propres particularités. Par défaut, l'unpacking itère sur les clés du dictionnaire :
# Unpacking des clés d'un dictionnaire
personne = {"nom": "Alice", "age": 30, "ville": "Paris"}
cle1, cle2, cle3 = personne
print(cle1) # nom
print(cle2) # age
print(cle3) # ville
Unpacking des valeurs et des paires
# Unpacking des valeurs
personne = {"nom": "Alice", "age": 30, "ville": "Paris"}
v1, v2, v3 = personne.values()
print(v1) # Alice
print(v2) # 30
print(v3) # Paris
# Unpacking des paires clé-valeur
for cle, valeur in personne.items():
print(f"{cle} : {valeur}")
# nom : Alice
# age : 30
# ville : Paris
L'opérateur ** pour les dictionnaires
L'opérateur ** (double splat) permet de "déballer" un dictionnaire, principalement pour fusionner des dictionnaires ou passer des arguments nommés à une fonction :
# Fusion de dictionnaires avec **
defauts = {"couleur": "bleu", "taille": "M", "stock": 10}
personnalisation = {"couleur": "rouge", "prix": 29.99}
produit = {**defauts, **personnalisation}
print(produit)
# {'couleur': 'rouge', 'taille': 'M', 'stock': 10, 'prix': 29.99}Remarquez que la clé couleur du second dictionnaire écrase celle du premier. L'ordre compte.
# Passer des arguments nommés avec **
def creer_profil(nom, age, ville):
return f"{nom}, {age} ans, habite à {ville}"
infos = {"nom": "Alice", "age": 30, "ville": "Paris"}
resultat = creer_profil(**infos)
print(resultat) # Alice, 30 ans, habite à Paris
Unpacking dans les fonctions
Paramètres *args et **kwargs
L'unpacking est au cœur du mécanisme des paramètres variadiques en Python. Lorsque vous définissez une fonction avec def, vous pouvez utiliser *args et **kwargs :
# *args capture les arguments positionnels dans un tuple
def somme(*args):
total = 0
for nombre in args:
total += nombre
return total
print(somme(1, 2, 3)) # 6
print(somme(10, 20, 30, 40)) # 100# **kwargs capture les arguments nommés dans un dictionnaire
def afficher_infos(**kwargs):
for cle, valeur in kwargs.items():
print(f"{cle} = {valeur}")
afficher_infos(nom="Alice", age=30, ville="Paris")
# nom = Alice
# age = 30
# ville = Paris
Unpacking lors de l'appel d'une fonction
Vous pouvez également utiliser * et ** pour "déballer" des arguments lors de l'appel d'une fonction :
def calculer_volume(longueur, largeur, hauteur):
return longueur * largeur * hauteur
# Unpacking d'une liste comme arguments positionnels
dimensions = [3, 4, 5]
volume = calculer_volume(*dimensions)
print(volume) # 60
# Unpacking d'un dictionnaire comme arguments nommés
dims = {"longueur": 3, "largeur": 4, "hauteur": 5}
volume = calculer_volume(**dims)
print(volume) # 60
Unpacking dans les boucles
L'unpacking est particulièrement utile dans les boucles, notamment avec enumerate et zip :
# Unpacking avec enumerate
fruits = ["pomme", "banane", "cerise"]
for index, fruit in enumerate(fruits):
print(f"{index}: {fruit}")
# 0: pomme
# 1: banane
# 2: cerise# Unpacking avec zip
noms = ["Alice", "Bob", "Charlie"]
ages = [30, 25, 35]
for nom, age in zip(noms, ages):
print(f"{nom} a {age} ans")
# Alice a 30 ans
# Bob a 25 ans
# Charlie a 35 ans# Unpacking de tuples imbriqués
points = [(1, 2), (3, 4), (5, 6)]
for x, y in points:
print(f"x={x}, y={y}")
# x=1, y=2
# x=3, y=4
# x=5, y=6
Unpacking imbriqué
Python supporte l'unpacking de structures imbriquées, ce qui est extrêmement puissant pour manipuler des données complexes :
# Unpacking imbriqué
data = ("Alice", (30, "Paris"), ["Python", "JavaScript"])
nom, (age, ville), langages = data
print(nom) # Alice
print(age) # 30
print(ville) # Paris
print(langages) # ['Python', 'JavaScript']# Unpacking imbriqué dans une boucle
employes = [
("Alice", ("Développeur", 45000)),
("Bob", ("Designer", 40000)),
("Charlie", ("Manager", 55000)),
]
for nom, (poste, salaire) in employes:
print(f"{nom} - {poste} : {salaire}€")
# Alice - Développeur : 45000€
# Bob - Designer : 40000€
# Charlie - Manager : 55000€
Cas d'usage avancés
Unpacking dans les compréhensions
# Unpacking dans une compréhension de liste
paires = [(1, "a"), (2, "b"), (3, "c")]
resultat = [f"{num}-{lettre}" for num, lettre in paires]
print(resultat) # ['1-a', '2-b', '3-c']
Unpacking avec des namedtuples et des dataclasses
L'unpacking fonctionne parfaitement avec les namedtuple et les dataclass :
from collections import namedtuple
Point = namedtuple("Point", ["x", "y", "z"])
p = Point(1, 2, 3)
x, y, z = p
print(x, y, z) # 1 2 3
Combiner * dans des littéraux
Depuis Python 3.5+, vous pouvez utiliser * et ** directement dans des littéraux de listes, tuples et dictionnaires :
# Combiner des listes avec *
liste1 = [1, 2, 3]
liste2 = [4, 5, 6]
combinee = [*liste1, *liste2, 7, 8]
print(combinee) # [1, 2, 3, 4, 5, 6, 7, 8]
# Créer un tuple combiné
t = (*liste1, *liste2)
print(t) # (1, 2, 3, 4, 5, 6)
# Combiner des sets
set1 = {1, 2, 3}
set2 = {3, 4, 5}
combine = {*set1, *set2}
print(combine) # {1, 2, 3, 4, 5}
Bonnes pratiques
| Pratique | Recommandation |
|---|---|
| Nombre de variables | Assurez-vous que le nombre de variables correspond au nombre d'éléments, ou utilisez * |
| Variables ignorées | Utilisez _ pour les valeurs que vous n'utilisez pas |
| Unpacking imbriqué | N'imbriquez pas au-delà de 2 niveaux pour garder la lisibilité |
| Nommage des variables | Donnez des noms explicites qui reflètent la signification des données |
| Échange de variables | Préférez a, b = b, a plutôt qu'une variable temporaire |
| Fusion de dicts | Utilisez {**d1, **d2} ou l'opérateur | (Python 3.9+) |
L'unpacking est une technique au cœur de la philosophie Python. Elle rend le code plus concis et plus expressif. N'hésitez pas à l'utiliser dès que vous manipulez des structures de données itérables.
Erreurs courantes à éviter
# ❌ Erreur : trop de valeurs à déballer
a, b = (1, 2, 3)
# ValueError: too many values to unpack (expected 2)
# ✅ Solution : utiliser *
a, b, *_ = (1, 2, 3)
# ❌ Erreur : pas assez de valeurs
a, b, c = (1, 2)
# ValueError: not enough values to unpack (expected 3, got 2)
# ✅ Solution : ajuster le nombre de variables
a, b = (1, 2)# ❌ Erreur : deux opérateurs * dans le même unpacking
*a, *b = [1, 2, 3, 4, 5]
# SyntaxError: multiple starred expressions in assignment
# ✅ Solution : un seul * autorisé
*a, b = [1, 2, 3, 4, 5]
Questions fréquentes
Quelle est la différence entre * et ** dans l'unpacking ?
L'opérateur * (simple étoile) est utilisé pour l'unpacking d'itérables séquentiels comme les list, les tuple et les sets. Il permet de capturer plusieurs éléments dans une liste ou de déballer une séquence en arguments positionnels. L'opérateur ** (double étoile) est exclusivement réservé aux dict : il déballe les paires clé-valeur en arguments nommés ou permet de fusionner des dictionnaires.
L'unpacking fonctionne-t-il avec n'importe quel itérable ?
Oui, l'unpacking fonctionne avec tout objet itérable en Python : tuples, listes, chaînes de caractères, sets, dictionnaires, générateurs (créés avec yield), résultats de enumerate, zip, et même vos propres objets itérables personnalisés créés avec class. La seule condition est que l'objet implémente le protocole d'itération.
L'unpacking a-t-il un impact sur les performances ?
L'unpacking en Python est une opération très optimisée au niveau de l'interpréteur. Son coût est négligeable et comparable à l'accès par index. Dans la grande majorité des cas, vous ne constaterez aucune différence de performance. Préférez toujours la lisibilité du code : l'unpacking rend le code plus clair et plus maintenable, ce qui est bien plus important que des micro-optimisations.
Comment apprendre à maîtriser l'unpacking et Python en général ?
L'unpacking est l'une des nombreuses techniques élégantes qui font la force de Python. Pour maîtriser ce concept ainsi que l'ensemble du langage de manière structurée, nous vous recommandons de suivre notre formation dédiée à Python sur Believemy. Vous y apprendrez progressivement toutes les notions essentielles, des bases jusqu'aux concepts avancés, avec des exercices pratiques à chaque étape.