Accueil

Tutoriel Python - sommaire

Découverte des tuples, dictionnaires et ensembles

Mais avant d'aborder ces trois types de données, je voudrais revenir sur l'activation des modules.

Instruction pour importer un module

Pour activer un module, j'écris souvent, par exemple, l'instruction suivante : from math import*
Or si vous avez consulté d'autres sources documentaires, vous avez pu lire : "import random" OU "import math"
Les deux solutions sont correctes.

Mais attention dans le deuxième cas nous devons alors préfixer les fonctions du nom du module.

N'en concluez pas que la première solution est la meilleure. C'est la préférable, si vous n'activez qu'un module.
Mais si vous en activez plusieurs modules, il faut mieux utiliser la deuxième solution.
En effet il est alors possible qu'il ait ambiguïté ... Deux modules employant le même mot pour désigner deux fonctions différentes ...

Dans le cadre de la première syntaxe je peux utiliser un alias (de préférence un mot court).
Exemple :

>>>import random as rd 
>>>rd.randint(100)
>>>rd.choice(chaine)

Traitements sur les listes

Avant d'aborder d'autres types de séquences qui existent en Python : tuples, dictionnaires et ensembles ; je voudrais vous montrer quelques traitements que l'on effectuer sur une liste.

Tirage au sort dans une liste simple

Petit programme à saisir et à tester :

# nom programme : choice_liste.py
import random
liste_simple =["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "kkk", "mmm", "nnn",
 "ooo", "ppp", "qqq", "rrr" ]
reponse ="o"
while reponse in "oO":
    element = random.choice(liste_simple)
    print ("élément tiré au sort : ", element)
    reponse = input("voulez vous continuez O/N ? : ")

Pour importer le module "random" j'ai employé la syntaxe "import nomModule" donc je dois ensuit préfixer les fonctions.
Notez la syntaxe pour extraire de façon aléatoire un élement : random.choice(liste_simple)

Tirage au sort dans une liste de listes

Dois-je vous rappeler qu'une liste peut être composée de sous-listes.

Petit programme à saisir et à tester :

# nom programme : choice_listedelistes.py
import random

listedelistes =[ ["aaa","1"],["bbb","2"],["ccc","3"],[ "ddd","4"],[ "eee","5" ],["fff","6"], 
["ggg", "7"],["hhh","8"],["kkk","9"] ,["mmm","10"], 
["nnn","11"],[ "ooo","12"],["ppp","13"],["qqq", "14"], ["rrr","15"] ]
reponse ="o"
while reponse in "oO": 
    sousliste = random.choice(listedelistes)
    print ("sous-liste tirée au sort  : ", sousliste[0], " " ,sousliste[1])
    reponse = input("voulez vous continuez O/N ? : ")

La liste comprend 15 sous-listes et chaque sous-liste comprend deux éléments.
La fonction choice() retourne une sous-liste ; il faut indicer pour accéder à chaque élément.

Convertir une liste en chaine

Il peut s'avérer utile de convertir une liste en chaine.
Commandes à tester dans la console :

>>> maliste = ["aaa", "bbb", "ccc", "dddd", "ffff", "eeee"] >>> type(maliste) <class 'list'> >>> machaine = " - ".join(maliste) >>> machaine 'aaa - bbb - ccc - dddd - ffff - eeee'

machaine = " - ".join(maliste) : la méthode join() a une syntaxe étrange ...
Elle convertit ici une liste en chaine. Les guillemets et les virgules internes sont remplacées ici par " - ". Les crochets disparaissent !

Méthodes pour modifier une liste

>>> maliste = ["aaa", "bbb", "ccc", "dddd", "ffff", "eeee"]
>>> maliste.reverse()
>>> maliste
['eeee', 'ffff', 'dddd', 'ccc', 'bbb', 'aaa']
>>> maliste.sort()
>>> maliste
['aaa', 'bbb', 'ccc', 'dddd', 'eeee', 'ffff']
>>> maliste.append('ggg')
>>> maliste.insert(2,'iii')
>>> maliste
['aaa', 'bbb', 'iii', 'ccc', 'dddd', 'eeee', 'ffff', 'ggg']
>>> maliste.remove('aaa')
>>> maliste
['bbb', 'iii', 'ccc', 'dddd', 'eeee', 'ffff', 'ggg']
>>>

Le type tuple

>>> montuple = (5,4,3,2,1) >>> type(montuple) <class 'tuple'>

Différences entre un tuple et une liste ?

Afficher un élément du tuple

 
>>> tuple3 ="louis", "paul", "henri"
>>> tuple3[1]
'paul'
>>> tuple3.index('henri')
2

On ne peut modifier un tuple mais on peut afficher un élément du tuple : sa valeur ou son indice.
Donc sur ce point, c'est exactement comme une liste.

Démontrons par l'exemple, qu'un tuple ne peut être modifié

 
>>> tuple3[2] = "henriette"
TypeError: 'tuple' object does not support item assignment
>>> tuple3 ="louis", "paul", "henri"
>>> tuple3.remove("louis")
AttributeError: 'tuple' object has no attribute 'remove'
>>> tuple3.append('denis')
AttributeError: 'tuple' object has no attribute 'append'

Un message d'erreur est affiché lorque l'on tente d'ajouter, supprimer, modifier un élément.

Production d'une chaine à partir d'un tuple

On ne peut pas modifier un tuple après qu'il ait été créé. Mais rien n'interdit de produire une chaine à partir d'un tuple comme le montre la suite de commandes ci-dessous :

>>> tuple3 =("louis", "paul", "henri")
>>> machaine = " * ".join(tuple3)
>>> machaine
'louis * paul * henri'
>>>

Emploi de la méthode join()

Pourquoi les tuples ?

On peut se demander à quoi ça peut bien servir ce type de données. En fait un tuple ça peut être très utile !

Un tuple permet une affectation multiple

>>> v1,v2 ="jacques", "louise"
>>> v1
'jacques'
>>> v2
'louise'

En une seule instruction on a initialisé deux variables avec un tuple.

Une fonction retournant plusieurs valeurs

Une fonction peut retourner un tuple de valeurs.
Exemple :

>>> def rectangle(lo,la):
...     p =(lo*2) + (la*2)
...     a = lo*la
...     return p, a
...
>>> perimetre,aire = rectangle(20,10)
>>> perimetre
60
>>> aire
200

La fonction "rectangle" retourne deux valeurs que je récupère dans un tuple à deux éléments.
Dans "perimètre" je récupère le contenu de la variable p de la fonction.
Dans "aire" je récupère le contenu de la variable a de la fonction.

Grâce aux tuples on peut permuter le contenu de deux variables

Exemple :

>>> r1 ="bonjour"
>>> r2 ="au revoir"
>>> r1,r2 = r2,r1  # de chaque côté de = on a des tuples
>>> r1
'au revoir'
>>> r2
'bonjour'

Notez bien la syntaxe r1,r2 = r2,r1 ; de chaque côté du signe "=" on a un tuple.

Créer des constantes dans un programme

Dans un programme il peut y avoir des variables qui ne peuvent être modifiées après avoir été initialisées. C'est ce qu'on appelle les constantes.
On peut donc créer ces constantes sous forme d'un tuple.
Exemple :

>>> taux_tva = 20, 5.5
>>> prix_ht = 1000
>>> prix_ht * taux_tva[0] /100
200.0
>>> taux_tva[0] = 18.6
Traceback (most recent call last):
  File "", line 1, in 
TypeError: 'tuple' object does not support item assignment

Les taux de TVA sont exprimés pour 100 €. Donc je dois diviser par 100 pour obtenir la TVA.
Notez que je n'arrive pas à modifier le contenu du tuple "taux_tva".

Exercice

Écrivez la fonction qui a partir du rayon retourne la circonférence et l'aire d'un cercle.
Donc argument à passer lors de l'appel de la fonction et deux valeurs retournées par cette fonction.

Tirage au sort d'un élément du tuple

Ci-dessous un programme qui accède de façon aléatoire à n éléments d'un tuple.

#nom prog : choice_tuple.py
import random
tuple1 = ("aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg", "hhh", "iii", "jjj",
 "kkk", "lll", "mmm")
reponse ="o"
while reponse in "oO":
    element = random.choice(tuple1)
    print ("élément tiré au sort : ", element)
    reponse = input("voulez vous continuez O/N ? : ")

Type dictionnaire

Dans un dictionnaire n'est pas une séquence d'éléménts simples mais de paires "clé:valeur". Un paire "clé:valeur" s'appelle aussi un item.
Les dictionnaires sont délimités par des accolades. Pour ceux qui connaissent le langage PHP, un dictionnaire Python c'est l'équivalent des tableaux associatifs en PHP.

Vous pouvez utiliser un dictionnaire pour réaliser un carnet d'adresses, dans lequel on accède à chaque contact en saisissant son nom.

Exemple

A tapez dans l'interpréteur :

>>> mon_inventaire ={"manteaux" : 2, "vestes" : 3, "chemises" : 6, "pantalons" : 5} >>> type(mon_inventaire) <class 'dict'> >>> mon_inventaire {'manteaux': 2, 'vestes': 3, 'chemises': 6, 'pantalons': 5} >>> mon_inventaire["pantalons"] 5 >>> machaine =" - ".join(mon_inventaire) >>> machaine 'manteaux - vestes - chemises - pantalons' >>> mon_inventaire["pulls"] = 10 >>> mon_inventaire {'manteaux': 2, 'vestes': 3, 'chemises': 6, 'pantalons': 5, 'pulls': 10} >>>del(mon_inventaire["vestes"]) .>>> mon_inventaire {'manteaux': 2, 'chemises': 6, 'pantalons': 5, 'pulls': 10}

Je crée un dictionnaire nommé "mon_inventaire" qui comprend 4 paires de clé-valeur.
Pour accéder à une valeur il faut préciser la clé. Syntaxe : nomDictionnaire [clé]. Ainsi j'apprends que j'ai 5 pantalons.
machaine =" - ".join(mon_inventaire) : création d'une chaine à partir du dictionnaire, avec la méthode join() ; seules les clés sont conservées dans la chaine de destination.
mon_inventaire["pulls"] = 10 : ajout d'un cinquième item au dictionnaire
del(mon_inventaire["vestes"]) suppression d'un item du dictionnaire

Parcours d'un dictionnaire

Attention un dictionnaire est une séquence non pas d'éléments mais d'items c'est à dire de couples "clé:valeur".

#nom programme : parcours_dico.py
#objet : parcours d'un dictionnaire

carnet = {"Pierre" : "pierre.dubus@gmail.com", "Pauline" : "duboispauline@hotmail.fr", "jacques" : "fredo_jacky@free.fr"}
for item in carnet.items():
    print(item)

Les noms des variables après le mot "for" n'ont aucune importance. Ce qui compte c'est d'appliquer la méthode items() à l'objet de type dictionnaire.

Exécution de ce programme :

Pierre   pierre.dubus@gmail.com
Pauline   duboispauline@hotmail.fr
jacques   fredo_jacky@free.fr

Pour afficher uniquement les clés il suffirait d'écrire :
for cle in carnet.keys():

Pour afficher uniquement les valeurs il suffirait d'écrire :
for valeur in carnet.values

Nous avons donc trois méthodes pour parcourir un dictionnaire : items(), keys(), values().

Les ensembles

Décidément Python n'est pas avare en structures de données.
Vous connaissiez les listes. Vous venez de voir les tuples et les dictionnaires.
Et bien depuis les dernières versions de Python, il existe un nouveau type de séquences de données : les ensembles (ou "set").

Différence entre un "dico" et un "set"

>>> mon_dico = {"cle1": 10, "cle2" : 15, "cle3":20} >>> type(mon_dico) <class 'dict'> >>> mon_set = {0,1,2,3,4,5} >>> type(mon_set) <class 'set'> >>> donnees = {} >>> type(donnees) <class 'dict'> >>> ensemble =set() >>> type(ensemble) <class 'set'> >>>

Tantôt la fonction type() retourne "dict" (comme dictionnaire) ou "set" (comme ensemble).
Il ne faut pas confondre les ensembles avec les dictionnaires.
Certes dans les deux cas les délimiteurs sont des accolades. Mais dans un ensemble il n'y a que des valeurs alors que dans un dictionnaire il y a des paires de clé-valeur.

Intérêt des ensembles

Puisqu'un "set" est une séquence de valeurs comme une liste, quel est l'intérêt pratique de cette nouvelle structure ???
À la différence d'une liste, un ensemble ne peut contenir une donnée qu'une fois. En d'autres termes, il ne peut y avoir de doublons dans un ensemble.

Création d'un ensemble

Il existe plusieurs façons de créer un ensemble.

Création d'un ensemble vide

Pour créer un dictionnaire vide, il suffit d'écrire : nomDico = {}
Pour créer une liste vide, il faut écrire : maListe =[]
Pour créer un ensemble vide, il faut écrire : nomSet = set()

À partir d'une saisie

>>> monset ={3,3,5,5}
>>> monset
>>> type(monset)

>>>
{3, 5}

Si vous tentez de saisir des doublons dans un ensemble, l'interpréteur ne signale aucune erreur mais élimine les doublons de la séquence.

À partir d'une liste

Création d'un "set" à partir d'une liste

>>> liste1 = [1,2,3,4,5,3]
>>> ensemble1 = set(liste1)
>>> ensemble1
{1, 2, 3, 4, 5}
>>>

Dans la liste d'origine il y avait un doublon qu'on ne retrouve plus dans l'ensemble de destination.

À partir d'une chaine de caractères

On peut convertir une séquence en un ensemble. Or une chaine de caractères est une séquence de caractères donc ...

>>> ensemble2 = set("anguille")
>>> ensemble2
{'l', 'a', 'n', 'i', 'u', 'e', 'g'}
>>> ensemble3 = set("lotte de mer")
>>> ensemble3
{'r', 'l', 'm', 'd', 'e', ' ', 'o', 't'}
>>>

Le mot "anguille" comprend deux "l". Dans le set "ensemble2" on ne retrouve qu'un "l".
Même type de remarque pour le set "ensemble2".

À partir de la fonction range()

On peut construire rapidement un "set" composé de nombres avec la fonction range().

>>> ensemble4 =set(range(1,10))
>>> ensemble4
{1, 2, 3, 4, 5, 6, 7, 8, 9}

Opérations sur les ensembles

Ajouter une valeur au "set"

>>> ensemble3.add('i')
>>> ensemble3
{'r', 'l', 'm', 'd', 'i', 'e', ' ', 'o', 't'}
>>> ensemble3.add('l')
>>> ensemble3
{'r', 'l', 'm', 'd', 'i', 'e', ' ', 'o', 't'}

On a pu ajouter la lettre "i' au set. Par contre la tentative d'ajout de la lettre "l" a échoué puisque cette valeur existait déjà dans le set.
Constatez qu'il n'y a jamais de message d'erreurs.

Vérifier l'existence d'une valeur dans le set

>>> 2 in ensemble4
True
>>> "a" in ensemble3
False
>>>

Parcourir un set

Parcourir un ensemble de lettres :

 
>>> for lettre in ensemble3:
...     lettre
...
'r'
'l'
'm'
'd'
'i'
'e'
' '
'o'
't'

Parcourir un ensemble de nombres :

>>> for chiffre in ensemble4:
...     print(chiffre)
...
1
2
3
4
5
6
7
8
9

En mode commande les commmandes "variable" et "print(variable)" ont le même rendu.
Notez que la syntaxe pour parcourir un ensemble, est très simple. Il n'est pas nécessaire de préciser le rang de l'élément. La notion d'indice de l'élément n'existe pas dans un set.

Vider un set de ses éléments

 
>>> ensemble4.clear()
>>> ensemble4
set()

Le set "ensemble4" est vide grâce à la méthode clear()

Supprimer un élément dans l'ensemble

>>> ensemble3.discard('i')
>>> ensemble3
{'r', 'l', 'm', 'd', 'e', ' ', 'o', 't'}
>>> ensemble3.discard('w')
>>> ensemble3.remove('w')
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'w'

Je supprime la lettre "i" du set puis je demande la suppression d'un élément qui n'existe pas ; l'interpréteur ne lève pas d'exception avec la méthode discard() mais signale une erreur avec la méthode remove().

Union de deux ensembles

>>> set1 = set(range(1,10))
>>> set1
{1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> set2 =set(range(5,12))
>>> set2
{5, 6, 7, 8, 9, 10, 11}
>>> set_union = set1.union(set2)
>>> set_union
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}

Le nouveau set ("set_union") est bien l'union de "set1" et "set2". Les valeurs communes aux deux ensembles d'origine ne sont présents qu'une fois.

Intersection de deux ensembles

>>> set_inter = set1.intersection(set2)
>>> set_inter
{5, 6, 7, 8, 9}

Le nouveau set ("set_inter") ne comprend que les éléments qui étaient communs aux deux ensembles d'origine : 5,6,7,8,9.

Convertir un ensemble en chaine

>>> ensemble1 = {"aaa", "bbb","ccc", "eee","ddd"} >>> type(ensemble1) <class 'set'> >>> machaine =" / ".join(ensemble1) >>> machaine 'aaa / ddd / eee / bbb / ccc'

Donc nous pouvons produire une chaine à partir d'un ensemble.

La méthode 'join()' peut s'appliquer à des listes, des tuples, des dictionnaires et des ensembles pour produire une chaine.

Exemple d'utilisation des ensembles

Deux plongeurs donnent la liste des poissons qu'ils ont pu observer dans un lac.
Vous devez en déduire la liste des poissons de ce biotope (sans doublons).

>>> plongeur1 = {"gardon", "goujon", "brème", "carpe", "rotengle", "barbeau", "silure"}
>>> plongeur2 = {"anguille", "alose", "gardon", "brochet", "perche", "barbeau", "poisson-chat"}
>>> liste_poissons = plongeur1.union(plongeur2)
>>> liste_poissons
{'brème', 'gardon', 'poisson-chat', 'barbeau', 'silure', 'goujon', 'alose', 'carpe', 'brochet',
 'anguille', 'perche', 'rotengle'}
>>> len(plongeur1)
7
>>> len(plongeur2)
7
>>> len(liste_poissons)
12

Deux espèces ont été signalées par les deux plongeurs.
Aucun doublon dans le nouveau set !

Programme basé sur un ensemble

Vous vous souvenez du programme qui consistait à tirer au sort cinq cartes.
Pour plaisanter, je disais même que ce programme trichait puisqu'une même carte pouvait être tirée 2 fois.
En utilisant un ensemble à la place d'une liste, nous n'aurons plus ce problème !

Le code

# nom programme : tirage_carte_plus.py
#objet : tirage au sort de 5 cartes.
""" Version améliorée :
les cartes tirées sont rangées dans un ensemble.
Ainsi il ne peut y avoir de doublons.
"""

from random import *
enseignes = ['pique', 'coeur', 'carreau', 'trèfle']
rang = ['As', 'Roi', 'Dame', 'Valet', 10, 9, 8 , 7]
reponse ="o"
while reponse in "Oo":
    mon_jeu =set()      # main stockée dans un ensemble
    for i in range(5):
        carte_e = choice (enseignes)
        carte_r = choice (rang)
        carte_tiree = str(carte_r) + " de " + carte_e
        mon_jeu.add(carte_tiree)

    print("Mon jeu : ")
     for carte in mon_jeu:
        print(carte, end =" - ")
    print ("\n Nombre de cartes de la main :", len(mon_jeu))
    print("----------------------------------------------")
    reponse =input("Encore un tirage o/n  ? : " ) 

Notez les commentaires multi-lignes.

Notez que la fonction len() fonctionne pour tous les types de séquences (liste, tuple, dictionnaire, ensemble).
Par contre pour ajouter un élément à un set, la méthode est add() et non pas append().

Trace de l'exécution

Mon jeu : 
Valet de trèfle - Roi de coeur - Dame de coeur - Dame de trèfle - 
 Nombre de cartes de la main : 4
----------------------------------------------
Encore un tirage o/n  ? : o
Mon jeu : 
Roi de pique - 9 de pique - 9 de trèfle - Valet de pique - 
 Nombre de cartes de la main : 4
----------------------------------------------
Encore un tirage o/n  ? : o
Mon jeu : 
As de coeur - Valet de pique - As de pique - 9 de pique - Dame de pique - 
 Nombre de cartes de la main : 5

Et oui, il y a encore un petit problème. Si la même carte est tirée au sort deux fois, l'ensemble ne comprend alors que 4 cartes (puisque les doublons sont interdits).

Il faudrait imaginer que dans ce cas (N cartes < à 5) il y ait un nouveau tirage.
C'est possible à condition de créer une fonction "tirage_carte" et d'appeler cette fonction dans le programme principal jusqu'à ce que le nombre de cartes dans la main soit de 5. C'est ce qu'on appelle faire de la programmation structurée.
Et oui, élaborer un programme parfait c'est parfois un long chemin ...

Fin de ce chapitre !

Concernant les structures itérables (listes, ensembles, dictionnaires, tuples et strings) je n'ai pas voulu tout traiter dans un seul chapitre ; ça aurait été trop indigeste. Ce chapitre est un survol, dans le chapitre 15 j'approfondis : chapitre XV

Dans le chapitre suivant trois nouveaux modules de Python : statistics, time & datetime.