Outils pour utilisateurs

Outils du site


nsi:premiere:dictionnaires

Ceci est une ancienne révision du document !



Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Warning: Undefined array key "pos" in /home/goupillf/wiki.goupill.fr/lib/plugins/mdpage/src/DokuWiki/Plugin/Mdpage/MarkdownRendererTrait.php on line 100

Dictionnaires

Problématique

Un tableau permet d'organiser des données en associant un item à un indice.

tableau[indice]item de rang i

Exemple : Jours de la semaine

jours = ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"]

Avec ce tableau on obtient facilement le jour d'indice 5 :

>>> jours[5]
"ven"

Mais comment faire des associations de type différent ?

Par exemple, on souhaite associer le nom d'une commune avec son gentilé (nom des habitants) :

gentilé = [
    ("Paris", "Parisien"),
    ("Marseille", "Marseillais"),
    ("Saint-Denis", "Dionysien"),
    ("Château-Thierry", "Castelthéodoricien")
]

Comment obtenir le gentilé pour "Saint-Denis" ?

C'est possible mais cela suppose de parcourir le tableau à la recherche de "Saint-Denis". On irait plus vite si on pouvait écrire quelque chose comme gentilé["Saint-Denis"]

Dictionnaire

On peut créer pour cela un dictionnaire :

gentilé = {
    "Paris":"Parisien",
    "Marseille":"Marseillais",
    "Saint-Denis":"Dionysien",
    "Château-Thierry":"Castelthéodoricien"
}

Ce qui produit exactement ce que l'on voulait :

>>> gentilé["Saint-Denis"]
"Dionysien"

Attention : Dans le dictionnaire, les deux éléments d'une paire n'ont pas le même rôle.

La partie à gauche de : est la clé, à droite c'est la valeur

>>> gentilé.keys()
['Paris', 'Marseille', 'Saint-Denis', 'Château-Thierry']
>>> gentilé.values()
['Parisien', 'Marseillais', 'Dionysien', 'Castelthéodoricien']

Et donc cette commande renvoie une erreur :

>>> gentilé["Dionysien"]
KeyError: "Dionysien"

Manipulations élémentaires

  • Nombre d'éléments

    >>> len(gentilé)
    4
  • Appartenance

    >>> "Paris" in gentilé
    True
    >>> "Lille" in gentilé
    False
  • Lecture

    >>> gentilé["Château-Thierry"]
    'Castelthéodoricien'
  • Ajout et modification

    >>> gentilé["Lille"] = "Lillois"
    >>> gentilé["Paris"] = "Parisienne"
  • Suppression

    >>> del gentilé["Château-Thierry"]

Énumération

Parcourir les éléments d'un dictionnaires. Comme pour un tableau, on peut désirer parcourir les clés, les valeurs ou les deux à la fois.

  • Parcourir par clé :

    for key in gentilé:
        ...
  • Parcourir par valeurs (a priori peu utile) :

    for item in gentilé.values():
        ...
  • Parcourir par paires :

    for key, item in gentilé.items():
        ...

Tuple nommé

Le programme fait référence à des tuples nommés.

Ce type de donnée n'existe pas nativement en Python (il faut importer une bibliothèque)

L'idée du programme est simplement d'utiliser, dans certains cas, des dictionnaires comme des tuples.

Cependant attention : un dictionnaire est mutable mais pas un tuple (on ne peut pas modifier un tuple une fois créé), c'est d'ailleurs ce qui fait la différence entre un tuple et un tableau.

Efficacité d'un dictionnaire

Comme on l'a dit, on pourrait créer un tableau de paires de valeurs ce qui permettrait, en parcourant le tableau, de retrouver tout ce que l'on veut :

gentilé = [
    ("Paris", "Parisien"),
    ("Marseille", "Marseillais"),
    ("Saint-Denis", "Dionysien"),
    ("Château-Thierry", "Castelthéodoricien")
]

Mais (déjà dit) pour trouver le gentilé de "Saint-Denis" (par exemple) il faut parcourir le tableau. Cela peut-être long si le tableau est grand.

Dans le cas d'un tableau, par exemple :

jours = ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"]

L'accès à un élement par son indice est direct :

>>> jours[5]

C'est à dire qu'il n'est pas nécessaire de parcourir "dim", "lun", etc. pour atteindre "ven", le programme saute directement à la bonne position.

Le dictionnaire permet de faire la même chose.

Un peu de technique Pour les plus avancés

De façon cachée pour l'utilisateur, quand on crée un dictionnaire, Python crée un tableau avec une taille fixée, par exemple 3.

Mais les clés de notre dictionnaire ne sont pas des nombres et ne sont donc pas des indices acceptables. Alors Python fait un calcul avec la clé :

>>> hash("Paris")
7211877366768910205

Il faut comprendre que "Paris", en mémoire est représenté comme un code binaire et que ce code binaire peut-être interprété comme un nombre et que l'on peut donc produire un nombre avec.

>>> hash("Paris") % 3
2

On place donc la paire ("Paris", "Parisien") au rang 2 du tableau.

Faisant le même travail avec les autres, Python créé (toujours de façon cachée) :

[ [],
  [("Saint-Denis", "Dionysien")],
  [("Paris", "Parisien"), ("Marseille", "Marseillais")]
]

Ensuite quand je demande gentilé["Paris"], le calcul hash("Paris") % 3 nous dit que l'on doit regarder à la case 2 et chercher dans les items qui s'y trouve.

Cela donne de bons résultats si chaque case est peu remplie. Python peut modifier la taille du tableau si le nombre d'éléments augmente, tout cela sans que l'utilisateur ait quoi que ce soit à faire.

Ce mécanisme est appelé une table de hachage.

Exercices

Exercice 1

On définit le dictionnaire suivant

Les retours à la ligne servent à la lisibilité, ils ne sont pas obligatoires.

d = {
    "France":"fr",
    "Royaume-Uni":"uk",
    "États-Unis":"us"
}

Que renvoient les commandes suivantes :

len(d)
type(d)
d["France"]
d["france"]
d["fr"]
"Italy" in d
"France" in d
"fr" in d
d["Espagne"]
d.keys()
d.values()
d.items()

Exercice 2 : Bibliothèques csv et panda

Vous disposez d'un fichier worldcities.csv contenant les données sur un ensemble de villes. Voici un aperçu du contenu de ce fichier :

city;city_ascii;lat;lng;country;iso2;iso3;admin_name;capital;population;id
Tokyo;Tokyo;35.6850;139.7514;Japan;JP;JPN;Tōkyō;primary;35676000;1392685764
New York;New York;40.6943;-73.9249;United States;US;USA;New York;;19354922.0;1840034016
Mexico City;Mexico City;19.4424;-99.1310;Mexico;MX;MEX;Ciudad de México;primary;19028000;1484247881

La première ligne est une entête qui sert à préciser le contenu des colonnes.

Nous avons déjà rencontré ce genre de fichier. Nous allons voir ici comment les bibliothèques csv et panda nous permettent d'accélérer le travail.

Créez un fichier city1.py

import de la bibliothèque.

import csv

Ouverture du fichier en mode lecture, avec l'encodage utf8.

file = open('worldcities.csv', 'r', encoding='utf8')

Création d'un objet de la bibliothèque csv chargé de lire le contenu de fichier. On précise le type de séparateur utilisé.

reader = csv.reader(file, delimiter=';')

reader est une sorte de tête de lecture. Nous allons faire avancer la tête de lecture pour récupérer les données du fichier et les stocker dans un tableau.

villes = []
for row in reader:
  villes.append(row)

On peut refermer le fichier.

file.close()

Pour mieux comprendre, demandons l'affichage du résultat (seulment les 5 premières lignes)

for i in range(5):
    print(villes[i])

Exécutez et visualisez le résultat.

Que constate-t-on ?

  • villes est un tableau contenant des lignes. Chaque ligne est également un tableau.
  • La première ligne du tableau est la ligne d'entête. Elle est peu exploitable.
  • Si on veut accéder au nom de pays de Tokyo, il faut déjà savoir que Tokyo est à la ligne 1 puis que le nom de pays est à la colonne 4 et demander villes[1][4].

Ce n'est pas tellement pratique.

Utilisation de dictionnaires.

On recommence, créez un fichier city2.py

Le début est le même :

import csv
file = open('worldcities.csv', 'r', encoding='utf8')

L'objet de lecture va être différent : il doit produire des dictionnaires.

reader = csv.DictReader(file, delimiter=';')

Puis lecture sous forme de dict

villes = []
for row in reader:
    villes.append(dict(row))

Et enfin fermeture du fichier.

file.close()

De nouveau, affichons les premiers éléments :

for i in range(5):
    print(villes[i])

Exécutez et visualisez le résultat.

Que constate-t-on ?

  • villes est toujours un tableau mais un tableau constitué de dictionnaires.

  • La première ligne du fichier, l'entête, n'est pas la première ligne de villes.

  • La ligne d'entête sert à former les clés des différents dictionnaires.

    Ainsi, si on veut atteindre le nom de de pays pour Tokyo, on écrira villes[1]['country']

L'utilisation de dictionnaires permet d'associer une étiquette à chaque colonne ce qui rend l'utilisation du fichier plus simple. On n'a pas besoin de s'ennuyer à chercher le numéro de colonne pour le pays, on indique directement 'country'.

Encore mieux avec panda

Panda est une bibliothèque très puissante et beaucoup utilisée pour le traitement de données.

Notez que c'est une spécificité de Python : on dispose de bibliothèque très puissantes qui permettent de réduire grandement le travail du programmeur.

On recommence, créez un fichier city3.py

Au lycée, pandas fonctionne seulement sur Pyzo, pas sur PythonEdu

Ajoutez seulement :

import pandas
villes = pandas.read_csv("worldcities.csv", delimiter=";")

villes n'est pas un tableau. C'est un objet défini par panda, plus compliqué et plein de fonctionnalités.

Voici quelques exemples que vous pouvez entrer en console après exécution du script :

>>> villes.loc[10] # affichage de l'item au rang 10
>>> villes.log[10]['population'] # population de cette ville.

Notez que population a été converti en float automatiquement par panda ce que ne faisait pas csv.

>>> villes.nlargest(10, 'population')
>>> villes[villes.city == "Paris"]

Ceci n'est qu'un aperçu, panda a beaucoup de fonctionnalités.

Exercice 3

Un brin d'ADN est une succession de bases nucléiques symbolisées par A, T, G, C pour adénine, thymine, guanine, cytosine. Une fonction de l'ADN est de coder les protéines que la cellule sera chargée de synthétiser. Pour se faire, un brin d'ADN complémentaire est créé :

A →U (uracile), T → A, G → C, C → G

puis chaque triplet - codon - de bases code une acide aminé.

Par exemple, UAU code pour Y : tyrosine

On vous fournit un fichier codons.csv précisant toutes les associations codon → acide aminé.

On vous fournit également un fichier adn.py qu'il faudra compléter.

Pour chacun des items suivant, produire une fonction :

  • testBrin(brinADN:str) -> bool

    Reçoit en entrée un brin d'ADN sous forme d'une chaîne. Renvoie True si le brin est valide (nombre de lettres multiple de 3)

  • brinComplementaire(brinADN:str) -> str

    Reçoit en entrée un brin d'ADN sous forme d'une chaîne. Renvoie la chaîne correspondant au brin complémentaire.

  • toAcides(brinADN:str) -> str

    Reçoit en entrée un brin d'ADN sous forme d'une chaîne. Renvoie la chaîne correspondant à la suite d'acides aminés.

nsi/premiere/dictionnaires.1618068808.txt.gz · Dernière modification : de goupillwiki