L'unpacking en Python
L' unpacking est un terme anglais que l'on pourrait traduire en français par « déballage ».
L'unpacking est très utile, mais difficile à expliquer et à comprendre tellement il peut servir dans de nombreux cas de figures.
Grâce à l'unpacking on peut par exemple « déballer » les éléments d'une liste dans plusieurs variables :
a, b, c = [1, 2, 3]
print(a)
print(b)
print(c)
Vous devez avoir le même nombre de valeurs de chaque côté du symbole d'égalité :
a, b, c, d = [1, 2, 3] # ValueError: not enough values to unpack (expected 4, got 3)
a, b, c = [1, 2] # ValueError: not enough values to unpack (expected 3, got 2)
On peut palier à ce problème avec l'opérateur splat (*
) qu'on accole à une
variable qui récupèrera toutes les valeurs permettant à l'itérable à droite du
symbole d'égalité d'être correctement « déballé » :
a, *b, c = (1, 2, 3, 4, 5, 6)
a -> 1
b -> [2, 3, 4, 5]
c -> 6
a, b, *c = (1, 2, 3, 4, 5, 6)
a -> 1
b -> 2
c -> [3, 4, 5, 6]
L'unpacking fonctionne avec tous les itérables :
a, b, c = (1, 2, 3) # Avec un tuple
print(a)
print(b)
print(c)
a, b, c = [1, 2, 3] # Avec une liste
print(a)
print(b)
print(c)
a, b, c = {1: "un", 2: "deux", 3: "trois"} # Avec un dictionnaire
print(a)
print(b)
print(c)
d, o, c, s, t, r, i, n, g = "Docstring" # Avec une chaîne de caractères
print(d)
print(o)
print(c)
print(s)
print(t)
print(r)
print(i)
print(n)
print(g)
Utilisations de l'unpacking
Dans les fonctions
On peut utiliser l'unpacking dans une fonction pour retourner plusieurs valeurs.
def validate_user(username, password):
if username == "Thibault" and password == "123":
return True, 827
user_is_valid, user_id = validate_user(username="Thibault", password="123")
print(user_is_valid)
print(user_id)
Comme pour les exemples ci-dessus, vous devez obligatoirement avoir le même
nombre de variables à gauche de l'opérateur =
lors de l'appel de la
fonction.
Ainsi, le code suivant vous retournera une erreur :
def validate_user(username, password):
if username == "Thibault" and password == "123":
return True # On ne retourne qu'une seule valeur
# On a deux variables à gauche du symbole d'égalité lors de l'appel de la fonction
user_is_valid, user_id = validate_user(username="Thibault", password="123")
print(user_is_valid)
print(user_id)
Par convention, on utilise un tiret du bas pour des variables dont nous n'avons pas besoin, mais que nous devons insérer dans un script pour prévenir les erreurs.
Si dans l'exemple de cette fonction, l'ID de l'utilisateur ne nous intéresse pas, nous pouvons donc faire :
def validate_user(username, password):
if username == "Thibault" and password == "123":
return True, 827
user_is_valid, _ = validate_user(username="Thibault", password="123")
print(user_is_valid)
print(_)
☝️ On indique ici avec le nom _
que cette variable n'aura pas d'utilité dans
le reste de notre script.
Dans une boucle
Dans le code ci-dessous, on utilise l'unpacking pour récupérer directement
dans deux variables séparées (i
et prenom
), les éléments contenus dans
chaque tuple de notre liste :
for i, prenom in [(1, "John"), (2, "Marie"), (3, "Julie")]:
print(i, prenom)
Ce principe est le même utilisé lorsque nous parcourons un dictionnaire avec
la méthode items
:
d = {1: "un", 2: "deux", 3: "trois"}
print(list(d.items()))
for key, value in d.items():
print(key, value)
Utilisations de l'unpacking dans l'appel d'une fonction
Il est également possible d'utiliser l'unpacking pour passer des arguments
lors de l'appel d'une fonction grâce à l'opérateur « splat » (*
) :
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b).upper()
rgb_values = (128, 255, 255)
# Sans l'unpacking
hex_value = rgb2hex(rgb_values[0], rgb_values[1], rgb_values[2])
# Avec l'unpacking
hex_value = rgb2hex(*rgb_values)
print(hex_value)
☝️ Dans cet exemple, la fonction rgb2hex
permet de convertir trois nombres
entiers allant de 0 à 255 et représentant les valeurs de rouge, de vert et de
bleu, en code couleur hexadécimal.
Plutôt que de passer les valeurs une à une avec leur indice, on utilise
l'opérateur splat (*
) pour « déballer » les valeurs et les donner
individuellement en argument à la fonction rgb2hex
.
Là encore, il faut faire attention aux nombres de valeurs qui sont passées, le
code suivant ne fonctionnera pas, car nous envoyons 4 valeurs à la fonction qui
n'en accepte que 3 (r
, g
et b
) :
def rgb2hex(r, g, b):
return "#{:02x}{:02x}{:02x}".format(r, g, b).upper()
rgba_values = (128, 255, 255, 0.5)
hex_value = rgb2hex(*rgba_values)
print(hex_value)