• Aucun résultat trouvé

12.6.1 Évitez les variables globales

Dans ce chapitre nous avons joué avec les fonctions (et les listes) afin de vous montrer comment Python réagissait. Toute-fois, notez bien que l’utilisation de variables globales est à bannir définitivement de votre pratique de la programmation. Parfois on veut faire vite et on crée une variable globale visible partout dans le programme (donc dans toutes les fonctions), car « Ça va plus vite, c’est plus simple ». C’est un très mauvais calcul, ne serait-ce que parce que vos fonctions ne seront pas réutilisables dans un autre contexte si elles utilisent des variables globales ! Ensuite, arriverez-vous à vous relire dans six mois ? Quelqu’un d’autre pourrait-il comprendre votre programme ? Il existe de nombreuses autres raisons3 que nous ne développerons pas ici, mais libre à vous de consulter de la documentation externe.

Heureusement, Python est orienté objet et permet « d’encapsuler » des variables dans des objets et de s’affranchir défini-tivement des variables globales (nous verrons cela dans le chapitre 19 Avoir la classe avec les objets). En attendant, et si vous ne souhaitez pas aller plus loin sur les notions d’objet (on peut tout à fait « pythonner » sans cela), retenez la chose suivante sur les fonctions et les variables globales :

Conseil

Plutôt que d’utiliser des variables globales, passez vos variables explicitement aux fonctions comme des argument(s).

12.7. Exercices Chapitre 12. Plus sur les fonctions

12.6.2 Modification d’une liste dans une fonction

Concernant les fonctions qui modifient une liste, nous vous conseillons de l’indiquer clairement dans votre code. Pour cela, faites en sorte que la fonction renvoie la liste modifiée et de récupérer cette liste renvoyée dans une variable portant le même nom. Par exemple :

1 def ajoute_un ( liste ):

2 for i in range ( len ( liste )): 3 liste [i] += 1

4 return liste 5

6 # Programme principal .

7 liste_notes = [10 , 8, 16, 7, 15] 8 liste_notes = ajoute_un ( liste_notes ) 9 print ( liste_notes )

La ligne 8 indique que la listeliste_notes passée à la fonction est écrasée par la liste renvoyée par la fonction. Le code suivant produirait la même sortie :

1 def ajoute_un ( liste ):

2 for i in range ( len ( liste )): 3 liste [i] += 1 4 5 # Programme principal . 6 liste_notes = [10 , 8, 16, 7, 15] 7 ajoute_un ( liste_notes ) 8 print ( liste_notes )

Cela reste toutefois moins intuitif car il n’est pas forcément évident de comprendre que la liste est modifiée dans la fonction en lisant la ligne 8. Dans un tel cas, il serait essentiel d’indiquer dans la documentation de la fonction que la liste est modifiée « sur place » (in place en anglais) dans la fonction. Vous verrez dans le chapitre 14 Création de modules comment documenter vos fonctions.

Conseil

Pour les raisons évoquées ci-dessus, nous vous conseillons de privilégier la première version :

1 liste_notes = ajoute_un ( liste_notes )

12.6.3 Conclusion

Vous connaissez maintenant les fonctions sous tous leurs angles. Comme indiqué en introduction du chapitre 9, elles sont incontournables et tout programmeur se doit de les maîtriser. Voici les derniers conseils que nous pouvons vous donner :

— Lorsque vous débutez un nouveau projet de programmation, posez-vous la question : « Comment pourrais-je décom-poser en blocs chaque tâche à effectuer, chaque bloc pouvant être une fonction ? ». Et n’oubliez pas que si une fonction s’avère trop complexe, vous pouvez également la décomposer en d’autres fonctions.

— Au risque de nous répéter, forcez-vous à utiliser des fonctions en permanence. Pratiquez, pratiquez. . . et pratiquez encore !

12.7 Exercices

Conseil: pour le second exercice, créez un script puis exécutez-le dans un shell.

12.7.1 Prédire la sortie

Prédisez le comportement des codes suivants, sans les recopier dans un script ni dans l’interpréteur Python :

Code 1

1 def hello ( prenom ):

2 print (" Bonjour {}". format ( prenom )) 3

4

Chapitre 12. Plus sur les fonctions 12.7. Exercices

5 # Programme principal . 6 hello (" Patrick ") 7 print (x)

Code 2

1 def hello ( prenom ):

2 print (" Bonjour {}". format ( prenom )) 3 4 5 # Programme principal . 6 x = 10 7 hello (" Patrick ") 8 print (x) Code 3

1 def hello ( prenom ):

2 print (" Bonjour {}". format ( prenom )) 3 print (x) 4 5 6 # Programme principal . 7 x = 10 8 hello (" Patrick ") 9 print (x) Code 4

1 def hello ( prenom ): 2 x = 42

3 print (" Bonjour {}". format ( prenom )) 4 print (x) 5 6 7 # Programme principal . 8 x = 10 9 hello (" Patrick ") 10 print (x)

12.7.2 Passage de liste à une fonction

Créez une fonctionajoute_nb_alea() qui prend en argument une liste et qui ajoute un nombre entier aléatoire entre -10 et 10 (inclus) à chaque élément. La fonction affichera à l’écran cette nouvelle liste modifiée.

Dans le programme principal, on effectuera les actions suivantes :

1. Créez une variablema_liste = [7, 3, 8, 4, 5, 1, 9, 10, 2, 6]. 2. Affichezma_liste à l’écran.

3. Appelez la fonctionajoute_nb_alea() en lui passant ma_liste en argument. 4. Affichez à nouveauma_liste à l’écran.

Chapitre 13

Dictionnaires, tuples et sets

Jusqu’à maintenant nous avons vu et manipulé le type d’objet séquentiel le plus classique : les listes. On se rappelle qu’elles sont modifiables, ordonnées et itérables. Dans ce chapitre nous allons voir trois nouveaux types d’objet séquentiel avec des propriétés différentes : les dictionnaires, les tuples et les sets.

Remarque

Les objets séquentiels peuvent être aussi appelés parfois containers.

13.1 Dictionnaires

13.1.1 Définition

Les dictionnaires se révèlent très pratiques lorsque vous devez manipuler des structures complexes à décrire et que les listes présentent leurs limites. Les dictionnaires sont des collections non ordonnées d’objets, c’est-à-dire qu’il n’y a pas de notion d’ordre (i.e. pas d’indice). On accède aux valeurs d’un dictionnaire par des clés. Ceci semble un peu confus ? Regardez l’exemple suivant :

1 >>> ani1 = {}

2 >>> ani1 [" nom "] = " girafe " 3 >>> ani1 [" taille "] = 5.0 4 >>> ani1 [" poids "] = 1100 5 >>> ani1

6 {'nom ': 'girafe ', 'taille ': 5.0 , 'poids ': 1100}

En premier, on définit un dictionnaire vide avec les accolades{} (tout comme on peut le faire pour les listes avec []). Ensuite, on remplit le dictionnaire avec différentes clés ("nom", "taille", "poids") auxquelles on affecte des valeurs ("girafe", 5.0, 1100). Vous pouvez mettre autant de clés que vous voulez dans un dictionnaire (tout comme vous pouvez ajouter autant d’éléments que vous voulez dans une liste).

Remarque

Un dictionnaire est affiché sans ordre particulier.

On peut aussi initialiser toutes les clés et les valeurs d’un dictionnaire en une seule opération :

1 >>> ani2 = {" nom ":" singe ", " poids ":70 , " taille ":1.75}

Mais rien ne nous empêche d’ajouter une clé et une valeur supplémentaire :

1 >>> ani2 [" age "] = 15

Pour récupérer la valeur associée à une clé donnée, il suffit d’utiliser la syntaxe suivantedictionnaire["cle"]. Par exemple :

1 >>> ani1 [" taille "] 2 5.0

Chapitre 13. Dictionnaires, tuples et sets 13.1. Dictionnaires

Remarque

Toutes les clés de dictionnaire utilisées jusqu’à présent étaient des chaînes de caractères. Rien n’empêche d’utiliser d’autres types d’objets comme des entiers (voire même des tuples, cf. rubrique suivante), cela peut parfois s’avérer très utile.

Néanmoins, nous vous conseillons, autant que possible, d’utiliser systématiquement des chaînes de caractères pour vos clés de dictionnaire.

Après ce premier tour d’horizon, on voit tout de suite l’avantage des dictionnaires. Pouvoir retrouver des éléments par des noms (clés) plutôt que par des indices. Les humains retiennent mieux les noms que les chiffres. Ainsi, l’usage des dictionnaires rend en général le code plus lisible. Par exemple, si nous souhaitions stocker les coordonnées (x, y, z) d’un point dans l’espace : coors = [0, 1, 2] pour la version liste, coors = {"x": 0, "y": 1, "z": 2} pour la version dictionnaire. Un lecteur comprendra tout de suite quecoors["z"] contient la coordonnée z, ce sera moins intuitif avec coors[2].

13.1.2 Itération sur les clés pour obtenir les valeurs

Il est possible d’obtenir toutes les valeurs d’un dictionnaire à partir de ses clés :

1 >>> ani2 = {'nom ':' singe ', 'poids ':70 , 'taille ':1.75} 2 >>> for key in ani2 :

3 ... print (key , ani2 [ key ]) 4 ...

5 poids 70 6 nom singe 7 taille 1.75

13.1.3 Méthodes .keys(), .values() et .items()

Les méthodes.keys() et .values() renvoient, comme vous pouvez vous en doutez, les clés et les valeurs d’un diction-naire :

1 >>> ani2 . keys ()

2 dict_keys ([' poids ', 'nom ', 'taille ']) 3 >>> ani2 . values ()

4 dict_values ([70 , 'singe ', 1.75])

Les mentionsdict_keys et dict_values indiquent que nous avons à faire à des objets un peu particuliers. Ils ne sont pas indexables (on ne peut pas retrouver un élément par indice, par exempledico.keys()[0] renverra une erreur). Si besoin, nous pouvons les transformer en liste avec la fonctionlist() :

1 >>> ani2 . values ()

2 dict_values ([' singe ', 70, 1.75]) 3 >>> list ( ani2 . values ())

4 ['singe ', 70, 1.75]

Toutefois, ce sont des objets « itérables », donc utilisables dans une boucle. Conseil: pour les débutants, vous pouvez sauter cette fin de rubrique.

Enfin, il existe la méthode.items() qui renvoie un nouvel objet dict_items :

1 >>> dico = {0: 't', 1: 'o', 2: 't', 3: 'o '} 2 >>> dico . items ()

3 dict_items ([(0 , 't '), (1, 'o '), (2, 't '), (3, 'o ')])

Celui-ci n’est pas indexable (on ne peut pas retrouver un élément par un indice) mais il est itérable :

1 >>> dico . items ()[2]

2 Traceback ( most recent call last ): 3 File "<stdin >", line 1, in <module >

4 TypeError : 'dict_items ' object is not subscriptable 5 >>> for key , val in dico . items ():

6 ... print (key , val ) 7 ...

8 0 t 9 1 o 10 2 t 11 3 o

Notez la syntaxe particulière qui ressemble à la fonctionenumerate() vue au chapitre 5 Boucles et comparaisons. On itère à la fois surkey et sur val. On verra plus bas que cela peut-être utile pour construire des dictionnaires de compréhension.