<jupyter_start><jupyter_text>Le but de ce document est de présenter les dictionnaires python. Les dictionnaires Définition : Les dictionnaires Un dictionnaire est une collection non-ordonnée (non indicée) d’objets (simples ou évolués) qui utilise le mécanisme associatif  clef-valeur. Une collection, c'est donc comme une liste mais là, elle n'est pas ordonnée : ça n'a pas de sens de dire qu'un élément est avant un autre puiqu'on va les appeler par leur nom (enfin leur clef !). En pratique : Utilisation des dictionnaires<jupyter_code>#définition d'un dictionnaire
age_eleve = {'Pierre':17, 'Paul':15,'Jacques':16}
print(age_eleve)<jupyter_output>{'Pierre': 17, 'Paul': 15, 'Jacques': 16}<jupyter_text>age_eleve est un dictionnaire, il est délimité par des {}.Pierre est une clef : key et 17 est la valeur : value associée à cette clef.  Accès à une valeur du dictionnaire à partir d'une clef Pour connaître l'âge de Pierre on écrit :age_eleve["Pierre"]<jupyter_code>age_eleve["Pierre"]<jupyter_output><empty_output><jupyter_text>Remarque : si on oublie les guillemets à "Pierre", l'interpréteur en déduit que l'on fait référence à une variable nommée Pierre, et il ne la connaît pas. Normal puisqu'ici, elle n'existe pas.<jupyter_code>age_eleve[Pierre]
#Alors que l'on peut utiliser une variable ainsi :
nom="Pierre"
age_eleve[nom]<jupyter_output><empty_output><jupyter_text>Pour savoir si une clef est présente dans un dictionnaire on utilise in :<jupyter_code>print("Pierre" in age_eleve)
print("Steven" in age_eleve)<jupyter_output><empty_output><jupyter_text>Parcours des valeurs d'un dictionnaire Pour énumérer toutes les valeurs d'un dictionnaire, on utilise une boucle après avoir créer un itérateur :  items() de ses éléments :<jupyter_code># age_eleve.item() est de type dict_item c'est une sorte de liste de tuples (clef,valeur)
age_eleve.items()
#Ce qui donne, avec une boucle for à deux variables clef,valeur :
for clef,valeur in age_eleve.items():
    print(clef+"\t", valeur) #\t est une tabulation, pour que les valeurs soient alignées.<jupyter_output><empty_output><jupyter_text>On aurait pu ne lister que les clefs :<jupyter_code>#liste des clés
for key in age_eleve.keys():
    print(key)<jupyter_output><empty_output><jupyter_text>Ou ne lister que les valeurs :<jupyter_code>#liste des valeurs :
for value in age_eleve.values():
    print(value)<jupyter_output><empty_output><jupyter_text>Remarque :Si on ne précise pas keys() ou values(), on itère par défaut sur les clefs :<jupyter_code>for element in age_eleve: #on itère sans préciser, sur les éléments du dictionnaire
    print(element)
print("--> On a obtenu une énumération des clefs.")<jupyter_output><empty_output><jupyter_text>Application aux données exif d'une image :Pour consulter les données exif d'une photo on peut utiliser le module exifread qui s'installe en ligne de commande par : $pip3 install exifread.Les données exif peuvent alors être récupérées sous forme de dictionnaire. Comme dans le code suivant :<jupyter_code>import exifread
import os
print("Le repertoire courant est : ", os.getcwd(),'\n')
# Ouverture d'une image pour lecture (en mode binaire)
f = open("ma_photo.jpg", 'rb')

# Retourne les Exif dans un dictionnaire (variable tags)
tags = exifread.process_file(f)
print(" "*(40-len("RUBRIQUE")),"RUBRIQUE"," | ","VALEUR")
print("-"*70)
for key, val in tags.items():
    if key!="JPEGThumbnail":
        compl=40-len(key)
        print(" "*compl,key," : ",val)<jupyter_output>Possibly corrupted field Tag 0x1490 in MakerNote IFD<jupyter_text>Travail demandé n°1 :1.Munis-toi d'une photo au format compressé jpeg et place-la dans le même répertoire que ce document sous le nom "ma_photo.jpg"2. A l'aide du code ci-dessus, retrouve et affiche les dates de prise de vue, la largeur et la hauteur, la durée d'exposition, l'ouverture (FNumber).3. Pendant combien de temps l'obturateur s'est-il ouvert durant la prise de vue ?  Les types de clefs Les clefs ne sont pas nécessairement de type string :<jupyter_code>#Des entiers pour les clefs
shifumi={1:"Pierre",2:"Feuille",3:"Ciseaux"}
from random import randint

#On associe ainsi à un tirage aléatoire : pierre, feuille ou ciseaux !
shifumi[randint(1,3)]<jupyter_output><empty_output><jupyter_text>On peut même utiliser des tuples soit pour la clef, soit pour la valeur, soit pour les deux :<jupyter_code>fiche_adherent={('Pierre',56):(15.4,'à jour de cotisation'),('Lucie',24):(15.1,'à jour de cotisation'),
                ('Pierre',22):(2.6,'à jour de cotisation'),('Lucie',3.2e6):('Non Classé', 'cotisation en retard')}
#Classement de l 'adhérent.e (on remarquera que sauf en cas d'ambiguité, les 
# parenthèses ne sont pas nécessaires pour appeler un tuple)
print("fiche_adherent['Lucie',24][0] renvoie : ",fiche_adherent['Lucie',24][0])<jupyter_output>fiche_adherent['Lucie',24][0] renvoie :  15.1<jupyter_text>Travail demandé n°2 :Dans la cellule ci-dessous, écrire un programme avec une boucle réalisant l'affichage suivant :![Image](fichier_adherent.png)<jupyter_code>#Etat de la cotisation annuelle :
print("\r") #Retour à la ligne
print("Fichier des adhérent.e.s :")<jupyter_output>Fichier des adhérent.e.s :<jupyter_text>Remarque.Il y a une restriction notable : __on ne peut pas utiliser une liste pour définir une clef__ .Une explication sur le wiki : les clefs doivent être *hachable* c'est-à-dire que leur valeur permet de calculer un entier qui ne change pas au cours du temps. C'est à cette condition que l'accès à une valeur par la clef via une *table de hash* sera performant.<jupyter_code>dico={[1,2]:'a'}<jupyter_output><empty_output><jupyter_text>Modification de valeur Les dictionnaires sont modifiables :<jupyter_code>#Si Lucie améliore sont classement on met à jour le dictionnaire :
fiche_adherent[('Lucie',24)]=(15.0,'à jour de cotisation')
#Classement de l 'adhérent.e
print(fiche_adherent[('Lucie',24)][0])<jupyter_output>15.0<jupyter_text>Avec un dictionnaire, pour ajouter une paire clef/valeur, il suffit d'écrire :<jupyter_code>#Si on veut rajouter le puits au shifumi, on rajoute une clef 4 et sa valeur "Puits" :
shifumi[4]="Puits"
#La liste shifumi devient :
print(shifumi)<jupyter_output>{1: 'Pierre', 2: 'Feuille', 3: 'Ciseaux', 4: 'Puits'}<jupyter_text>Alors que l'équivalent avec une liste conduit à un message d'erreur index out of range :<jupyter_code>#Créons une liste pour notre exemple :
liste_nature=['arbre','fruit','feuille']
print(liste_nature[1])
#On voudrait rajouter un élément au rang suivant (3) de la liste en faisant :
liste_nature[3]='fleur'
#Il aurait fallu écrire :
liste_nature.append('fleur')
liste_nature<jupyter_output><empty_output><jupyter_text>Travail demandé n°3 :1.Reprends les donnees exif de la photo vue ci-dessus et modifie le Copyright en ajoutant ton nom.2.Affiche à nouveau les données et vérifie qu'elles ont bien été modifées. Création en compréhension A l'instar d'une liste, on peut créer un dictionnaire en compréhension !Dans l'exemple qui suit, on crée la table ascii des lettres majuscules :<jupyter_code># chr(n) renvoie le caractère ascii correspondant à un entier.
print("Dans la table ascii 65 correspond au caractère",chr(65))

#On génère le dictionnaire associant l'entier à la lettre de l'alphabet majuscule :
numero_table_ascii={chr(n): n for n in range(65, 65+26)}

print("Table ascii par lettre :")
print(numero_table_ascii)
#Ou à l'inverse avec la fonction ord() qui renvoie l'entier correponsdant à un caractère ascii :
print("L'entier correspondant au caractère a dans la table ascii est",ord('a'))
#On génère le dictionnaire associant la lettre de l'alphabet minuscule au nombre entier entre 97 et 122 :
caractere_ascii={ord(i):i for i in "abcdefghijklmnopqrstuvwxyz"}
print("Table ascii par numéro :")
print(caractere_ascii)
#Remarque :
############
#Pour avoir l'alphabet de façon savante, on peut utiliser le module string :
import string
print("l'alphabet est :", string.ascii_lowercase)
#Faire help('string') pour les autres attributs possibles de string<jupyter_output>l'alphabet est : abcdefghijklmnopqrstuvwxyz<jupyter_text>Travail demandé n°4 :On considère la chaîne de caractère (string) :" >La caméra volante nous pistait depuis notre entréesur l'anneau périphérique. Dès la rampe, j'avais décon-necté le pilote et poussé le bobsleigh à deux cents -"(<NAME> - La Zone du Dehors).Construire un dictionnaire dont les clefs sont les caractères ascii utilisés dans la citation et les valeurs, le nombre d'occurences de chaque caractère (on ne prendra pas en compte les sauts de ligne). Solution:<jupyter_code>#Placer la solution ici :<jupyter_output><empty_output><jupyter_text>Travail demandé n°5 : chiffrement d'un message.1.Créer un dictionnaire dans lequel chaque caractère est une clef, et sa valeur est un caractère différent.2.Réécrire la string chaine avec ce nouvel alphabet.3.A quelle condition le message est-il facilement déchiffrable ?4.Ecrire un programme de déchiffrement du message.<jupyter_code>#Placer la solution ici :<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09705295812098383, 'fraction_numerical': 0.01229780633724795, 'mean_word_length': 6.158604282315623, 'pattern_counts': {'":': 1, '<': 71, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '19', 'dir': 'jupyter-structured-clean-dedup', 'id': '6638', 'license': 'CC0-1.0', 'n_tokens_mistral': 3320, 'n_tokens_neox': 3250, 'n_words': 1065, 'path': 'Types_construits/Les_dictionnaires/Les dictionnaires - Tableaux associatifs.ipynb', 'repo_name': 'FDehove/NSI-1ere', 'size': '9030'}