Python L1, TD/TP 18.03

N'oubliez pas que vous avez aujourd'hui un exercice obligatoire ! Il sera consacré aux dictionnaires. Vous avez 4 jours [depuis la publication de ce texte] pour travailler ce sujet en profondeur. Je suggère de travailler très sérieusement sur les trois premiers exercices.


Dictionnaires ; quelques exercices utiles

(Il est improbable que nous puissions traiter tous les exercices, mais entraînez-vous off-line)

Exercice 1. Code de César.

Une technique cryptographique très superficielle et primitive est basé sur le suivant.


Exercice 2. Dictionnaires et Bases de Données.

Une base de données relationnelle peut être considéré comme un ensemble de tables, où chaque table est une collection d'associations clé → valeur, donc représentable par un dictionnaire Python. Voici un exemple, une petite base de compositeurs et oeuvres, avec deux tables, les compositeurs :

comp            a_naiss  a_mort

Mozart          1756     1791
Beethoven       1770     1827
Haendel         1685     1759
Schubert        1797     1828
Vivaldi         1678     1741
Monteverdi      1567     1643
Chopin          1810     1849
Bach            1685     1750
et les oeuvres (pièces, représentations) :
comp            titre                           duree       interpr

Vivaldi         Les quatre saisons              20          T. Pinnock
Mozart          Concerto piano N°12             25          M. Perahia
Brahms          Concerto violon N°2             40          A. Grumiaux 
Beethoven       Sonate "au clair de lune"       14          W. Kempf
Beethoven       Sonate "pathétique"             17          W. Kempf
Schubert        Quintette "la truite"           39          SE of London
Haydn           La création                     109         H. Von Karajan
Chopin          Concerto piano N°1              42          M.J. Pires
Bach            Toccata & fugue                 9           P. Burmester
Beethoven       Concerto piano N°4              33          M. Pollini
Mozart          Symphonie N°40                  29          F. Bruggen
Mozart          Concerto piano N°22             35          S. Richter
Beethoven       Concerto piano N°3              37          S. Richter
Une table sera donc représentée en Python comme une liste de dictionnaires :
compositeurs = [{'comp':'Mozart', 'a_naiss':1756, 'a_mort':1791},
                {'comp':'Beethoven', ''a_naiss':1770, ...},
                {'Haendel': ...  }, ... ]
et la table d'oeuvres aura la représentation similaire.


Exercice 3. Opérations "ensemblistes".
Étant donnés deux dictionnaires, d1 et d2, construire un nouveau dictionnaire qui contient les éléments de d1 si, et seulement si la clé en question n'existe pas en d2, ou elle existe, mais la valeur associée est différente.


Exercice 4. Vous devez déjà savoir, que globals() retourne le dictionnaire système, dont les clés sont les noms (chaînes) des variables Python dans l'environnement global courant, et les valeurs, sont les valeurs associées à ces variables
Écrire un programme, qui demande à l'utilisateur une chaîne - nom de variable, et une valeur (textuelle ou numérique, car vous ne savez pas encore construire d'autres objets), et qui créé une variable avec ce nom et valeur dans l'environnement global. Si cette variable existe déjà, le programme doit émettre un avertissement, demander la réponse à la question : "remplacer ou non?", et effectuer (ou non) l'opération.


Exercice 5. Analyse fréquentielle.
Cet exercice est le "pain quotidien" dans le traitement des langues (une des options en L2, très intéressante, car ouvre vos esprits vers les technologies comme la correction automatique d'orthographe, moteurs de recherche, etc.). Étant donnée une liste de mots, construire le graphique qui montre la fréquence des mots dans ce texte, en fonction de leurs longueurs.

Commençons par vous donner quelques utilitaires, dont tôt ou tard tous ceux qui programment en Python auront besoin. Lisons un texte depuis un fichier en ligne, vous le devez importer chez vous. C'est un chapitre de livre de Verne "20 000 mille lieues sous les mers". Son codage est Unicode, UTF-8 ; ne vous inquiétez pas des détails.

f=open("../Txt/nemo.txt",encoding="utf-8") # Mode par défaut : READ ("r")
s=f.read()
La variable s contient la chaîne avec tout. Si vous n'arrivez pas à la récupérer, appelez-moi, probablement vous adressez mal ce fichier, après l'avoir importé ; l'exemple montre MON environnement.

Ensuite il faut séparer les mots. Ceci est une manipulation si courante, qu'une grande machinerie, dite d'expressions régulières (Regular Expressions, regexp, RE) a été conçu pour des problèmes de ce genre (et qui est, par ex., essentielle dans la compilation des langages.) Pour vous il suffit d'exécuter :

import re
l=re.split('\W+',s)
("\W+" signifie : une ou plusieurs occurrences d'un caractère qui n'appartient pas à un mot au sens habituel, une séquence de lettres). Sur l'exemple cité, vous devez obtenir :
l=['', 'LES', 'DERNIÈRES', 'PAROLES', 'DU', 
 'CAPITAINE', 'NEMO', 'Les', 'panneaux', 's', 
 'étaient', 'refermés', 'sur', 'cette', 'vision', 
 'effrayante', 'mais', 'la', 'lumière', 'n', 
 'avait', ...]
Cependant vous pouvez prendre un autre texte sur l'Internet ou un de vos documents privés.

À présent construisez un dictionnaire qui accumule, ajoute 1 (un) sous la clé numérique N, par ex. 6, chaque fois quand on trouve un mot de longueur N. Vous devez obtenir le dictionnaire : {0: 2, 1: 207, 2: 612, 3: 328, 4: 321, 5: 248, 6: 221, 7: 193, 8: 156, 9: 120, 10: 75, 11: 33, 12: 19, 13: 5, 14: 7, 15: 2, 16: 1}, mais les clés peuvent figurer dans l'ordre différent ! Il faut construire une liste de tuples [(0, 2), (1, 207), (2, 612), (3, 328), (4, 321), ...], et la trier, à l'aide de la procédure sorted. (D'ailleurs, ici la longueur 0 est un cas dépourvu de sens, vous pouvez effacer cette entrée si vous voulez).

Construisez la liste des longueurs : [0, 1, 2, ...] ainsi que la liste de valeurs correspondantes [2, 207, 612, ...], et affichez le graphique, comme celui à droite.


Exercice 6. Graphes

Nous avons vu qu'un dictionnaire peut représenter un graphe, avec les étiquettes des noeuds (sommets) comme clés, et comme valeurs – les listes de noeuds-cibles. Le graphe de l'exemple de la semaine dernière est représenté par :

{'A': ['H', 'C'],
 'B': ['A'],
 'C': ['G', 'E'],
 'D': ['B'],
 'E': [],
 'F': ['B'],
 'G': [],
 'H': []}


Retour à Matplotlib

Exercice 7. Images...

Revenez au dernier exercice de la semaine dernière.
Avec imshow(...) on peut créer un graphique contenant une image, et ensuite dessiner sur cette image. Mais au lieu de dessiner on peut faire d'autres manipulations. Quand ginput() récupère les coordonnées de la souris, par une simple arithmétique on peut trouver les indices de l'élément du tableau, qui correspond au point cliqué. Nous pouvons ensuite modifier la valeur de cet élément, et ceci peut être utilisé pour changer la couleur de cet élément. Donc, par exemple, voici la création d'un tableau avec des éléments aléatoires :

n=35
aa=random((n,n))*256
Mais vous pouvez aussi utiliser une vraie image lue par imread() dans un tableau, assembler une liste de listes, etc. Ensuite :
im=imshow(aa,cmap='hsv',interpolation="nearest") # par exemple
...
x,y = ginput()[0]
j,k = ... indices depuis x,y
aa[j,k] =  ...
Cependant ceci ne suffit pas pour changer l'apparence visuelle du tableau, l'affectation modifie le tableau dans la mémoire, mais il faut aussi dire à Matplotlib de mettre à jour le graphique. Il faut effectuer
im.set_array(aa)
draw()
La commande im.set_array remplace la structure interne du graphique par la valeur aa modifiée. Cette structure est une copie du tableau aa, la modification de l'original ne change pas l'affichage.

Codez cet exemple. Chaque case cliquée doit changer la couleur aléatoirement (random()*256). Je veux voir vos résultats. Attention, si on ne définit pas les limites des axes, imshow les déclare entre -0.5, et n-0.5, pour la dimension horizontale et verticale (qui peuvent être différentes). Ceci vous sera utile pour convertir ginput() en indices.


Exercice 8.

Images couleur "vraie" (sans palettes).

Lisez cela soigneusement. Vous avez vu des exemples d'images 2D : tableaux, ou listes de listes T. Les valeurs des éléments peuvent être conventionnelles, on a déjà utilisé 0 - 1, mais conventionnellement ce sont les nombres entre 0 - 255. Chaque valeur de T[i,j] est convertie en indice dans un dictionnaire spécial : la palette (grise, "HSV" similaire aux colueurs spectrales, vert-jaune, etc. Il y en a plusieurs, et on peut en faire d'autres).

Cependant, des photos, et plusieurs images synthétiques sont en couleur directe, le tableau est 3-dimensionnel, avec la hauteur et la largeur quelconques, et avec la troisième dimension - les 3 plans de couleur : n×m×3. [Parfois 4, avec le quatrième plan étant lA transparence/opacité]. Donc, on aurait besoin de listes de listes de listes, si au lieu de tableaux numpy on utilisait des listes Python.

Les valeurs des éléments de la structure affichée sont des réels entre 0 et 1. 0 signifie "noir" (pas de couleur), 1 : couleur pleine. Le premier plan de couleur est rouge, le second - vert, le troisième - bleu. Les combinaisons donnent des couleurs intermédiaires. Par ex. rouge plein et vert plein, sans bleu, donne la couleur jaune, et trois plans identiques donnent une nuance de gris.

Construisez un tableau ou liste 3-dim (liste de listes de listes), dont le troisième plan est égal à zéro (pas de bleu). Le premier plan (indice 0, rouge) contient les nombres entre 0 (en haut) et 1 (en bas), donc le niveau du rouge augmentera verticalement (le long de chaque colonne ; les colonnes sont identiques).
Le second plan (vert) contient également les valeurs entre 0 à 1, mais horizontalement (les lignes sont identiques).

Ne vous trompez pas : Pour une liste de listes en tant qu'image, c'est une liste de lignes. Pour un tableau, le premier indice identifie la ligne, le second - la colonne.

Obtenir l'image comme celle ci-dessus.


Exercice 9. Boutons cliquables.

Matplotlib n'a pas été conçu pour créer des interfaces visuelles, mais le paquetage dispose d'une bonne collections de widgets interactifs : cases à cocher, boutons, sliders, textes, menus, tables, etc. Seulement il n'y a pas (encore) de dispositifs comme "pack" ou "grid" de tkinter, ce qui facilite l'organisation spatiale des widgets, leur disposition. Il faut le faire manuellement, mais c'est facile.

Il faut manuellement créer on objet avec son propre système de coordonnées, donc en cohérence avec tout Matplotlib, on définit des axes spécialement pour des boutons. Si vous codez :

f=figure()
axbut = axes([0.6, 0.3, 0.2, 0.1])
butsuiv = Button(axbut, 'Suivant',
    color='g',hovercolor='y')
vous aurez le dessin à droite. Les axes du bouton sont déclarées dans le système de coordonnées de la figure, conventionnelles, entre 0 et 1. Donc [x0,y0,w,h] spécifie un rectangle avec le coin gauche bas à x0, y0, largeur w et hauteur h, en fractions des dimensions de la figure.

Les deux couleurs sont : normale, et quand la souris passe au dessus. On peut cliquer le bouton, mais ceci ne fait rien. Il faut spécifier
butsuiv.on_clicked(fonction)
Alors quand le bouton est activé, la fonction fonction est appelée, sans paramètres.

Votre exercice consiste à créer une figure avec 12 boutons, en grille 3×4. 10 cases contiennent les chiffres 0, 1, ... 9. L'onzième est le point ".", et le douzième : une flèche, ou un symbole similaire (peu importe). Quand on clique sur un chiffre, ou le point, le caractère en question est affiché sur la console. La flèche fait afficher le retour chariot, et on peut créer un autre nombre.

Ceci est le début d'un squelette simpliste d'une 'calculatrice', on va la faire en douceur. L'étape suivante sera consacré aux boutons - opérateurs ("+", "-", "*", "/", "=") et l'annulation, et la création d'un champs textuel : simplement un "sous-plot" (axes) de couleur différente, où on pourra placer le widget textuel text(...). Mais tout ceci demande un peu de patience.

N'oubliez pas qu'un devoir maison vous attend, vous allez représenter des automates cellulaires comme des lignes dans un tableau Matplotlib, une cellule par colonne. L'évolution d'un automate sera représentée comme la construction de la ligne suivante, en dessous de la courante. Le processus sera animé, les lignes vont défiler vers le haut, et l'état de la cellule sera représenté par sa couleur.


Semaine dernière
Semaine suivante
Retour à l'index