Python est le langage de programmation le plus utilisé. Aujourd’hui, vous apprendrez à utiliser l’une de ses principales fonctionnalités, souvent ignorée, à savoir le déballage en Python.
Vous avez probablement vu * et ** dans le code d’autres personnes ou même les avez utilisés sans vraiment savoir à quoi ils servent. Nous allons parcourir le concept d’unpacking, et comment l’utiliser pour écrire du code plus Python.
Voici une liste de concepts que vous trouverez utiles en lisant ce tutoriel :
- Itérable: Toute séquence qui peut être itérée par une boucle for, comme les ensembles, les listes, les tuples et les dictionnaires
- Appelable: Un objet Python qui peut être appelé en utilisant des doubles parenthèses (), par exemple, myfunction()
- Shell : Environnement d’exécution interactif qui nous permet d’exécuter du code Python. Nous pouvons l’appeler en lançant “python” dans un terminal
- Variable : Nom symbolique qui stocke un objet et dispose d’un emplacement mémoire réservé.
Commençons par la confusion la plus fréquente : Les astérisques en Python sont aussi des opérateurs arithmétiques. Un astérisque (*) est utilisé pour la multiplication, tandis que deux astérisques (**) se réfèrent à l’exponentiation.
Pour s’en convaincre, il suffit d’ouvrir un shell Python et de taper :
>>> 3*3
9
>>> 3**3
27
Note : Vous devez avoir installé Python 3 pour suivre ce tutoriel. Si ce n’est pas le cas, consultez notre guide d’installation de Python.
Comme vous pouvez le voir, nous utilisons l’astérisque après le premier nombre et avant le second. Cela signifie que nous utilisons les opérateurs arithmétiques.
D’autre part, nous utilisons les astérisques (*, **) devant un itérable pour le décompresser – par exemple :
>>> *range(1, 6),
(1, 2, 3, 4, 5)
>>> {**{'vanille':3, 'chocolat':2}, 'fraise':2}
{'vanille' : 3, 'chocolat' : 2, 'fraise' : 2}
Ne vous inquiétez pas si vous ne comprenez pas, il s’agit juste d’un préambule à la décomposition en Python. Allez-y, lisez le tutoriel en entier !
Qu’est-ce que le déballage ?
Le déballage est le processus qui consiste à sortir des choses – des itérables tels que des listes, des tuples et des dictionnaires. Imaginez que vous ouvrez une boîte et que vous en sortez différents objets comme des câbles, des écouteurs ou une clé USB.
Traduisons ce même exemple en code pour une meilleure compréhension :
>>> mybox = ['cables', 'headphones', 'USB']
>>> item1, item2, item3 = mybox
Comme vous pouvez le voir, nous assignons les trois éléments de la liste mybox à trois variables item1, item2, item2. Ce type d’affectation de variable est le concept fondamental du déballage en Python.
Si vous essayez d’obtenir la valeur de chaque élément, vous remarquerez que item1, fait référence aux “câbles”, item2, fait référence aux “écouteurs” et ainsi de suite.
>>> item1
'câbles'
>>> item2
'écouteurs'
>>> élément3
uSB
Jusqu’ici, tout semble bien se passer avec ce code, mais que se passerait-il si nous voulions décompresser une liste avec plus d’éléments, tout en gardant le même nombre de variables assignées ?
>>> newbox = ['cables', 'headphones', 'USB', 'mouse']
>>> élément1, élément2, élément3 = newbox
Traceback (dernier appel le plus récent) :
Fichier "<stdin>", ligne 1, in <module>
ValueError : too many values to unpack (expected 3)
Vous vous attendiez probablement à ce genre d’erreur. Essentiellement, nous assignons 4 éléments de liste à trois variables, comment Python parvient-il à assigner les bonnes valeurs ?
Il ne le fait pas, c’est pourquoi nous obtenons une ValueError avec le message “too many values to unpack”. Cela se produit parce que nous définissons trois variables à gauche, et quatre valeurs (correspondant à la liste newbox) à droite.
Si vous essayez d’effectuer un processus similaire, mais avec plus de variables que de valeurs à décompresser, vous obtiendrez une autre ValueError , mais avec un message légèrement différent :
>>> lastbox = ['cables', 'headphones']
>>> item1, item2, item3 = lastbox
Traceback (dernier appel le plus récent) :
Fichier "<stdin>", ligne 1, in <module>
ValueError : pas assez de valeurs à décompresser (attendu 3, obtenu 2)
Note : Nous avons travaillé avec des listes mais vous pouvez utiliser cette forme de déballage avec n’importe quel itérable (listes, ensembles, tuples, dictionnaires)
Comment surmonter cette situation ? Existe-t-il un moyen de décompresser tous les éléments d’un itérable en quelques variables sans obtenir d’erreurs ?
Bien sûr qu’il y en a un, et il s’appelle l’opérateur de déballage ou l’opérateur d’astérisque (*, **). Voyons comment l’utiliser en Python.
Comment décompresser des listes avec l’opérateur *
L’opérateur astérisque (*) est utilisé pour décompresser toutes les valeurs d’un itérable qui n’ont pas encore été assignées.
Supposons que vous souhaitiez obtenir le premier et le dernier élément d’une liste sans utiliser d’index, nous pourrions le faire avec l’opérateur astérisque :
>>> first, *unused, last = [1, 2, 3, 5, 7]
>>> premier
1
>>> dernier
7
>>> inutilisé
[2, 3, 5]
Comme vous pouvez le constater, nous obtenons toutes les valeurs inutilisées avec l’opérateur astérisque. La meilleure façon d’éliminer des valeurs est d’utiliser une variable soulignée (_), qui est parfois utilisée comme “variable fictive”.
>>> first, *_, last = [1, 2, 3, 5, 7]
>>> _
[2, 3, 5]
Nous pouvons utiliser cette astuce même si la liste ne comporte que deux éléments :
>>> first, *_, last = [1, 2]
>>> premier
1
>>> dernier
2
>>> _
[]
Dans ce cas, la variable de soulignement (variable fictive) stocke une liste vide afin que les deux autres variables qui l’entourent puissent accéder aux valeurs disponibles de la liste.
Dépannage courant
Nous pouvons décompresser un élément unique d’un itérable. Par exemple, vous obtiendrez quelque chose comme ceci :
>>> *string = 'PythonIsTheBest'
Cependant, le code ci-dessus renverra une SyntaxError:
>>> *string = 'PythonIsTheBest'
Fichier "<stdin>", ligne 1
SyntaxError : starred assignment target must be in a list or tuple (la cible de l'affectation étoilée doit être une liste ou un tuple)
Ceci parce que selon la spécification PEP:
Un tuple (ou une liste) du côté gauche d’une affectation simple
Si nous voulons décompresser toutes les valeurs d’un itérable en une seule variable, nous devons mettre en place un tuple, donc l’ajout d’une simple virgule sera suffisant :
>>> *chaîne, = 'PythonIsTheBest'
>>> string
['P', 'y', 't', 'h', 'o', 'n', 'I', 's', 'T', 'h', 'e', 'B', 'e', 's', 't']
Un autre exemple serait l’utilisation de la fonction range, qui renvoie une séquence de nombres.
>>> *nombres, = range(5)
>>> nombres
[0, 1, 2, 3, 4]
Maintenant que vous savez comment décompresser les listes et les tuples avec un astérisque, il est temps de décompresser les dictionnaires.
Comment décompresser les dictionnaires avec l’opérateur ** ?
Alors qu’un simple astérisque est utilisé pour décompresser les listes et les tuples, le double astérisque (**) est utilisé pour décompresser les dictionnaires.
Malheureusement, nous ne pouvons pas décompresser un dictionnaire en une seule variable comme nous l’avons fait avec les tuples et les listes. Cela signifie que ce qui suit provoquera une erreur :
>>> **greetings, = {'hello' : 'HELLO', 'bye' : 'BYE'}
...
SyntaxError : syntaxe non valide
Cependant, nous pouvons utiliser l’opérateur ** à l’intérieur de callables et d’autres dictionnaires. Par exemple, si nous voulons créer un dictionnaire fusionné, composé d’autres dictionnaires, nous pouvons utiliser le code ci-dessous :
>>> nourriture = {'poisson':3, 'viande':5, 'pâtes':9}
>>> couleurs = {'rouge' : 'intensité', 'jaune' : 'bonheur' }
>>> merged_dict = {**alimentation, **couleurs}
>>> merged_dict
{'poisson' : 3, "viande" : 5, 'pâtes' : 9, 'rouge' : 'intensité', 'jaune' : 'bonheur' }
Il s’agit d’une méthode assez courte pour créer des dictionnaires composés, mais ce n’est pas l’approche principale du déballage en Python.
Voyons comment nous pouvons utiliser l’unpacking avec les callables
Emballage dans les fonctions : args et kwargs
Vous avez probablement déjà vu des args et des kwargs, qu’ils soient implémentés dans des classes ou des fonctions. Voyons pourquoi nous avons besoin de les utiliser avec des objets appelables.
Emballage avec l’opérateur * (args)
Supposons que nous ayons une fonction qui calcule le produit de deux nombres.
>>> def product(n1, n2) :
... retour n1 * n2
...
>>> nombres = [12, 1]
>>> product(*nombre)
12
Comme vous pouvez le voir, nous décompressons la liste des nombres dans la fonction, ce qui nous permet d’exécuter ce qui suit :
>>> product(12, 1)
12
Jusqu’à présent, tout fonctionne parfaitement, mais que se passerait-il si nous voulions passer une liste plus longue ? Il y aura certainement une erreur car la fonction reçoit plus d’arguments qu’elle n’est capable d’en gérer.
>>> nombres = [12, 1, 3, 4]
>>> product(*nombre)
...
TypeError : product() prend 2 arguments positionnels mais 4 ont été donnés
Nous pouvons résoudre tout cela en plaçant la liste directement dans la fonction, ce qui crée un itérable à l’intérieur et nous permet de passer n’importe quel nombre d’arguments à la fonction.
>>> def product(*args) :
... result = 1
... for i in args :
... result *= i
... return result
...
>>> produit(*nombre)
144
Ici, nous traitons le paramètre args comme un itérable, parcourant ses éléments et renvoyant le produit de tous les nombres. Notez que le nombre de départ du résultat doit être un, car si nous commençons par zéro, la fonction renverra toujours zéro.
Note : args est juste une convention, vous pouvez utiliser n’importe quel autre nom de paramètre
Nous pouvons également passer des nombres arbitraires à la fonction sans utiliser de liste, comme avec la fonction print intégrée.
>>> product(5, 5, 5)
125
>>> print(5, 5, 5)
5 5 5
Enfin, obtenons le type d’objet des arguments d’ une fonction.
>>> def test_type(*args) :
... print(type(args))
... print(args)
...
>>> test_type(1, 2, 4, 'une chaîne')
<classe 'tuple'>
(1, 2, 4, 'une chaîne')
Comme indiqué dans le code ci-dessus, le type de args sera toujours un tuple, et son contenu sera constitué de tous les arguments sans mot-clé transmis à la fonction.
Emballage avec l’opérateur ** (kwargs)
Comme nous l’avons vu précédemment, l’opérateur ** est utilisé exclusivement pour les dictionnaires. Cela signifie qu’avec cet opérateur, nous pouvons passer des paires clé-valeur à la fonction en tant que paramètre.
Créons une fonction make_person, qui reçoit un argument positionnel “name” et un nombre indéfini d’arguments de type mot-clé.
>>> def make_person(name, **kwargs) :
... result = name ' : '
... for key, value in kwargs.items() :
... result = f'{key} = {value}, '
... return result
...
>>> make_person('Melissa', id=12112, location='london', net_worth=12000)
'Melissa : id = 12112, location = london, net_worth = 12000, '
Comme vous pouvez le voir, l’instruction **kwargs convertit tous les arguments du mot-clé en un dictionnaire, que nous pouvons itérer à l’intérieur de la fonction.
Remarque : kwargs n’est qu’une convention, vous pouvez nommer ce paramètre comme vous le souhaitez
Nous pouvons vérifier le type des kwargs de la même manière que pour les args:
>>> def test_kwargs(**kwargs) :
... print(type(kwargs))
... print(kwargs)
...
>>> test_kwargs(random=12, parameters=21)
<classe 'dict'>
{'random' : 12, 'parameters' : 21}
La variable interne kwargs est toujours un dictionnaire, qui stocke les paires clé-valeur transmises à la fonction.
Enfin, utilisons args et kwargs dans la même fonction :
>>> def my_final_function(*args, **kwargs) :
... print('Type args : ', type(args))
... print('args : ', args)
... print('Type kwargs : ', type(kwargs))
... print('kwargs : ', kwargs)
...
>>> my_final_function('Python', 'The', 'Best', language='Python', users='A lot')
Type args : <classe 'tuple'>
args : ('Python', 'The', 'Best')
Type kwargs : <classe 'dict'>
kwargs : {'language' : 'Python', 'users' : 'A lot'}
Conclusion
Les opérateurs de déballage sont vraiment utiles dans les tâches quotidiennes, maintenant vous savez comment les utiliser à la fois dans les déclarations individuelles et les paramètres de fonction.
Dans ce tutoriel, vous avez appris :
- Vous utilisez * pour les tuples et les listes et ** pour les dictionnaires
- Vous pouvez utiliser les opérateurs de déballage dans les fonctions et les constructeurs de classes
- lesargs sont utilisés pour passer des paramètres sans mot-clé aux fonctions
- kwargs est utilisé pour passer des paramètres avec mot-clé aux fonctions.
Ensuite, vous apprendrez à utiliser les opérateurs Python Not Equal.