Introduction
L’opérateur astérisque (*
) de Python est plus puissant qu’il n’y paraît. Bien que les débutants le rencontrent souvent d’abord dans le contexte de la multiplication, il joue un rôle beaucoup plus vaste et élégant lorsqu’il s’agit de déballer des itérables, de collecter des arguments de fonctions, et de manipuler des structures de données dynamiques.
Table des matières
- Introduction
- Que signifie « déballer » ?
- Déballage de base de listes/tuples avec *
- Déballage de base de dictionnaires avec **
- *args et **kwargs dans les fonctions
- Déballage dans les appels de fonction
- Fusion et copie d’itérables avec *
- Déballage dans les boucles
- Déballage de structures imbriquées
- Pièges courants
- Tableau récapitulatif
- Conclusion
Dans cet article, nous allons explorer comment *
et son homologue à double astérisque **
sont utilisés pour déballer et reconditionner les données en Python.
Que signifie « déballer » ?
Déballer, c’est extraire les valeurs d’un itérable (comme une liste, un tuple, un ensemble ou une chaîne) et les affecter à des variables individuelles. C’est la manière qu’a Python de dire : « Décompose cette collection et distribue les éléments. »
Deux types principaux de déballage :
- Déballage à gauche : Distribution des éléments dans des variables (
a, *reste = iterable
) - Déballage dans les arguments de fonctions : Passage des éléments en arguments avec
*
ou**
Déballage de base de listes/tuples avec *
Python permet de déballer les valeurs directement dans des variables. L’opérateur *
rend cela plus flexible en collectant le reste des éléments dans une liste :
1 2 3 4 | a, b, *reste = [1, 2, 3, 4, 5] print(a) # 1 print(b) # 2 print(reste) # [3, 4, 5] |
On peut placer *
à différentes positions :
1 2 3 4 5 6 | *debut, fin = [10, 20, 30, 40] print(debut) # [10, 20, 30] print(fin) # 40 premier, *milieu, dernier = [1, 2, 3, 4, 5] print(milieu) # [2, 3, 4] |
⚠️ On ne peut utiliser qu’une seule cible étoilée (
*
) par affectation.
Déballage de base de dictionnaires avec **
Le double astérisque **
permet de déballer des dictionnaires — une fonctionnalité puissante pour fusionner des dictionnaires ou passer leurs contenus à des fonctions sous forme d’arguments nommés.
Exemple de base
1 2 3 4 | dict1 = {"a": 1, "b": 2} dict2 = {"c": 3} fusion = {**dict1, **dict2} print(fusion) # {'a': 1, 'b': 2, 'c': 3} |
Ce qu’il se passe ici :
**dict1
déballe les paires clé-valeur dedict1
.**dict2
déballedict2
de la même façon.- Le résultat est un nouveau dictionnaire combiné.
Fonctionnalité introduite avec Python 3.5+.
Écrasement des clés
Si les deux dictionnaires ont la même clé, le dernier l’emporte :
1 2 3 4 | dict1 = {"a": 1, "b": 2} dict2 = {"b": 99, "c": 3} fusion = {**dict1, **dict2} print(fusion) # {'a': 1, 'b': 99, 'c': 3} |
Fusion de plusieurs dictionnaires
1 2 3 4 5 | d1 = {"x": 1} d2 = {"y": 2} d3 = {"z": 3} fusion = {**d1, **d2, **d3} print(fusion) # {'x': 1, 'y': 2, 'z': 3} |
Avec des littéraux
1 2 3 | defaults = {"theme": "light", "font": "Arial"} settings = {**defaults, "font": "Helvetica", "size": 12} print(settings) # {'theme': 'light', 'font': 'Helvetica', 'size': 12} |
Cas limites
1 2 3 4 5 6 7 | bad = [("a", 1), ("b", 2)] # ❌ TypeError: 'list' object is not a mapping # fusion = {**bad} # Solution : valid = dict(bad) fusion = {**valid} |
Comparaison avec update()
{**d1, **d2}
crée un nouveau dictionnaire.d1.update(d2)
modified1
en place.
Code:
1 2 3 4 | d1 = {"a": 1} d2 = {"b": 2} fusion = {**d1, **d2} d1.update(d2) # modifie d1 |
Utilisez **
si vous souhaitez préserver l’immuabilité.
*args
et **kwargs
dans les fonctions
Python permet à une fonction d’accepter un nombre variable d’arguments :
*args
: arguments positionnels (regroupés en tuple)**kwargs
: arguments nommés (regroupés en dictionnaire)
Exemple *args
1 2 3 4 5 | def saluer(*noms): for nom in noms: print(f"Bonjour, {nom}!") saluer("Alice", "Bob", "Charlie") |
Sortie:
1 2 3 | Bonjour, Alice! Bonjour, Bob! Bonjour, Charlie! |
Exemple **kwargs
1 2 3 4 5 | def afficher_infos(**infos): for cle, valeur in infos.items(): print(f"{cle}: {valeur}") afficher_infos(nom="Dana", age=30, role="Ingénieure") |
Sortie:
1 2 3 | name: Dana age: 30 role: Engineer |
Déballage dans les appels de fonction
Vous pouvez déballer un itérable ou un dictionnaire pour passer ses valeurs à une fonction :
1 2 3 4 5 | def addition(a, b, c): return a + b + c nombres = [1, 2, 3] print(addition(*nombres)) # 6 |
Avec un dictionnaire :
1 2 3 4 5 | def introduire(nom, age): print(f"{nom} a {age} ans.") info = {'nom': 'Dana', 'age': 30} introduire(**info) |
Fusion et copie d’itérables avec *
Fusion de listes
1 2 3 4 | liste1 = [1, 2] liste2 = [3, 4] fusion = [*liste1, *liste2] print(fusion) # [1, 2, 3, 4] |
Copie superficielle
1 | copie = [*liste1] |
Fusion de dictionnaires
1 2 3 | d1 = {'a': 1} d2 = {'b': 2} fusion = {**d1, **d2} |
Déballage dans les boucles
1 2 3 4 5 6 7 | data = [(1, 2, 3), (4, 5, 6)] for a, *milieu, c in data: print(milieu) # Affiche : # [2] # [5] |
Déballage de structures imbriquées
1 2 3 4 5 6 | nested = [(1, (2, 3)), (4, (5, 6))] for x, (y, z) in nested: print(x, y, z) # x=1, y=2, z=3 # x=4, y=5, z=6 |
Avec longueurs variables :
1 2 3 | nested = [(1, (2, 3, 4)), (5, (6, 7))] for x, (y, *reste) in nested: print(f"x={x}, y={y}, reste={reste}") |
Pièges courants
-
❌ Un seul
*
autorisé par déballage :1 2
# ❌ Invalid # a, *b, *c = [1, 2, 3]
-
*
et**
ne fonctionnent que sur des itérables. -
Lors du déballage dans une fonction, le nombre d’éléments doit correspondre à sa signature (sauf avec
*args
ou**kwargs
).
Tableau récapitulatif
Cas d’usage | Exemple de syntaxe |
---|---|
Affectation avec reste | a, *b = [1, 2, 3] |
Fonction à arguments variables | def f(*args): |
Fonction à mots-clés variables | def f(**kwargs): |
Déballer une liste dans une fonction | f(*[1, 2, 3]) |
Déballer un dictionnaire dans une fonction | f(**{'x': 1, 'y': 2}) |
Fusionner des listes | [ *a, *b ] |
Fusionner des dictionnaires | { **d1, **d2 } |
Boucle avec reste | for a, *b, c in data: |
Conclusion
Les opérateurs *
et **
sont des outils essentiels pour écrire un code Python clair, concis et élégant. Ils facilitent la gestion des arguments, le déballage de données, la fusion de structures, et la manipulation de données complexes ou de longueur variable.
Savoir quand et comment les utiliser rendra votre code non seulement plus court — mais aussi plus lisible, plus propre, et plus "pythonic".