On appelle iterable unpacking (on peut dire aussi tuple unpacking) une opération qui consiste à affecter, à plusieurs variables en même temps, contenues dans un tuple ou une liste, le contenu d'un iterable, en une seule opération d'affectation. Exemple:
>>> (a, b, c) = (10, 20, 30)
>>> a
10
>>> b
20
>>> c
30
Les tuples pouvant s'écrire sans parenthèses (à part dans certaines circonstances où les parenthèses sont utiles pour délimiter le tuple, comme lorsqu'il est passé en paramètre d'une fonction), on peut aussi écrire des 2 façons équivalentes ci-dessous:
>>> a, b, c = (10, 20, 30)
>>> a, b, c = 10, 20, 30
A gauche du signe = peut être une liste également, dans ce cas les crochets sont obligatoires (sinon ça serait un tuple par défaut):
>>> [a, b, c] = 10, 20, 30
A droit du signe = peut être n'importe quel iterable:
>>> a, b, c = [10, 20, 30]
>>> a, b, c = range(3)
>>> a
0
>>> b
1
>>> c
2
>>> a, b, c = "hey"
>>> a
'h'
>>> b
'e'
>>> c
'y'
L'iterable à droit du signe = peut contenir des éléments plus complexes, cela ne change rien au mécanisme d'unpacking, par exemple un tuple
de tuples:
>>> a, b, c = (10, 20), (30, 40), (50, 60)
>>> a
(10, 20)
>>> b
(30, 40)
>>> c
(50, 60)
S'il y a trop ou pas assez de valeurs à "unpacker" (si on peut transformer le mot anglais unpack en verbe français), on a une erreur explicite:
>>> a, b = 1, 2, 3
ValueError: too many values to unpack (expected 2)
>>> a, b, c = 1, 2
ValueError: not enough values to unpack (expected 3, got 2)
Dans le cas précédent où il y a trop de valeurs, on peut utiliser l'opérateur *. Dans ce contexte cet opérateur s'appelle l'opérateur
d'unpacking, il permet d'assigner plusieurs valeurs à une seule variable, cela est possible en faisant pointer cette variable vers une nouvelle
liste qui contiendra toutes les valeurs correspondantes. Le terme exact en Python pour cet opérateur est starred expression (expression
étoilée). Exemple:
>>> a, *b = 1, 2, 3
>>> a
1
>>> b
[2, 3]
>>> a, b, *c = 1, 2, 3
>>> a
1
>>> b
2
>>> c
[3]
>>> *a, = 1, 2, 3
>>> a
[1, 2, 3]
Dans le dernier exemple ↑ on écrit *a, = 1, 2, 3 et non pas *a = 1, 2, 3 car c'est imposé par la syntaxe des littéraux pour les
tuples: un tuple contenant un seul élément doit obligatoirement avoir une virgule avant la fin, sinon on pourrait confondre avec les parenthèses de
priorité des opérations si le tuple a des parenthèses, ou bien avec une expression hors d'un tuple si le tuple n'a pas de parenthèses.
Les variables sans * sont prioritaires sur celle avec *, de sorte que l'* ne "capte" pas toutes les valeurs, par exemple:
>>> *a, b = 1, 2, 3
>>> a
[1, 2]
>>> b
3
>>> a, *b, c = 1, 2, 3
>>> a
1
>>> b
[2]
>>> c
3
>>> a, *b, c = 1, 2, 3, 4
>>> a
1
>>> b
[2, 3]
>>> c
4
>>> a, *b, c = 1, 2
>>> a
1
>>> b
[]
>>> c
2
Il est impossible d'utiliser plusieurs * dans une même expression:
>>> *a, *b = 1, 2, 3
SyntaxError: multiple starred expressions in assignment
La fonctionnalité d'iterable unpacking est utile en soi, mais aussi dans certaines situations particulières que nous verrons plus loin dans ce cours.