Python a une documentation interne, que l'on peut appeler avec la variable spéciale doc pour quasiment chaque fonction, méthode ou objet interne à python ('builtin'). Pour y accéder dans l'interpréteur :
print str.__doc__
C'est intéressant si l'on connait le nom de l'objet qui nous intéresse bien sûr ! Pour connaître toutes les variables et méthodes associées à un objet, on utilise la fonction dir():
dir(str) dir(list)
Et pour connaître la liste des éléments au coeur de python :
dir(__builtins__)
Installez le paquet 'python-doc' (sous debian/ubntu) et vous aurez également accès à une documentation complète (/usr/share/doc/python-doc/html/index.html). En particulier, /usr/share/doc/python-doc/html/lib/lib.html contient tous les détails nécessaires sur les éléménts par défaut de python.
Le but de ce cours est de découvrir des éléments qui vous permettrons d'écrire une petite application de répertoire téléphonique. On voudrait avoir un menu qui propose de faire plusieurs choses :
| ajouter un contact |
| en supprimer un |
| en modifier un |
| lister tous les contacts (par ordre alphabétique) |
| lister les contacts commençant pour une lettre en particuler |
| quitter |
Ce dont on va avoir besoin :
Le menu devra apparaître indéfiniment, ce n'est pas possible avec les éléments de controle qu'on a déjà vu (if, for). On va donc utiliser une boucle <em>while</em>. while ('tant que') s'utilise comme ceci :
while (condition est vraie): #faire des actions #et d'autres
par exemple :
i = 0 while (i < 10): i = i+1 print i
Attention à ce genre de boucle, qui peut vite devenir infinie :
i = 1 while (i > 0): i = i + 1
Que se passe-t-il ? On ne sort jamais de la boucle.
Mais justement, pour notre application on va vouloir une telle boucle, qui demande sans cess à l'utilisateur, jusqu'à ce qu'il demande d'en sortir (i.e. quitter). C'est l'instruction break qui va nous permettre de quitter la boucle :
i = 1 while (i > 0): i = i + 1 if i > 10: break else: print "Toujours dans la boucle" print "Adieu la boucle"
Vous avez tous les éléments qu'il faut pour gérer votre menu.
Il y a sans doute plusieurs façons de gérer les couples nom/n° de tel, voyons une solution qui me paraît pratique, et qui permet de découvrir un nouveau type : les dictionnaires. Les dictionnaires sont des listes de clé/valeur, que l'ont définit comme ceci :
dico = {1: "tada", 2: "hello", "cle": 4, "cle2": "valeur"}
Contrairement aux listes, il n'y a pas de notion d'ordre, puisque l'idée d'un dictionnaire est de proposer une correspondance clé/valeur. On accède à une valeur par:
dico[cle]
où cle est évidemment une des clés du dictionnaire.
Exercice : quelles méthodes existent pour un dictionnaire ('dict' dans le langage python) ? Exercice2 : voyons les noms des méthodes, lisez la doc qui leur correspond, et trouvez un moyen de lister tous les couples du dictionnaire 'dico' (hint : 'for' utilisé pour les listes marche aussi pour les dictionnaires)
Utiliser des fonctions !
Un mot sur la portée des variables. Chaque variable déclarée a une portée, c'est à dire qu'elle n'est valable que dans le bloc courant (et les sous blocs). Par exmple :
def foo(): a = 5 a = 4 foo() # à priori on change la valeur print a # mais non !
La variable a à l'intérieur de la fonction n'est pas la même que celle en dehors. Pour utiliser la même variable on, doit dire à la fonction d'utiliser la variable a globale :
def foo(): globla a a = 5 a = 4 foo() print a # on a vraiment changé la valeur cette fois ci
Pour notre programme, on peut choisir de définir le dictionnaire qui contiendra nos valeurs comme variable globale, qui sera accessible dans toutes les fonctions du programme. Bien évidemment il est plus que conseillé de définir des fonctions qui exécuteront telle ou telle action du programme, par exemple :
def del_item(nom): # blabla def add_item(nom, no_tel, confirm=True): # bla bla
etc…
Notez que la fonction add_item prend 3 arguments dont 2 obligatoires (les 2 premiers). Si le 3ème argument n'est pas donné, python utilisera une valeur par défaut ('True' dans notre cas). Lors des appels à la fonction, les arguments doivent être donnés dans l'ordre trouvé dans la déclaration.
Pour documenter vos fonctions, vous pouvez définir une “docstring”, c'est à dire le texte qui sera accessible par l'appel à 'fonction.doc' :
def une_fonction(): """une_fonction ne fait rien Cette fonction ne fait rien, et ne prend pas d'argument """ pass
Le mot clé 'pass' permet de ne rien faire (python oblige à avoir une commande dans un bloc).
Une bonne idée pour construire votre script est de définir les divers opérations qu'il sera amené à faire, et de définir les fonctions en conséquences (leur nom, leurs arguments, leur valeur de retour).
Pour sauvegarder vos données, on peut simplement écrire le dictionnaire que vous aurez créé dans un fichier. Il existe des méthodes pour écrire le dictionnaire en soit dans des fichiers, mais voyons une méthode plus primaire. Lire et écrire des fichiers est de toute manière quelque chose que vous aurez à faire presque constamment.
Un fichier s'ouvre avec l'instruction 'open', qui prend en argument le chemin/nom du fichier, et le méthode d'ouverture (lecture, écriture, ajout). Cette instruction retourne un objet, descripteur de fichier :
f = open("/home/gauvain/python.txt", "w")
f est le descripteur du fichier, ouvert en écriture. On aurait utilisé “r” pour une simple lecture, “a” pour de l'ajout. “w” écrase complètement le fichier. Pour ajouter du texte dans ce fichier, il suffit simplement d'utiliser la méthode write :
f.write("J'écris une ligne dans le fichier\n")
Le '\n' final correspond à un saut de ligne. Une fois le fichier rempli avec ce que vous voulez, il faut le fermer :
f.close()
Votre fichier est enregistré ! Pour sauver notre dictionnaire, on peut tout à fait imaginer une boucle qui lit toutes les entrées du dictionnaire, et qui à chaque fois écrit une ligne du type :
nom prénom:014546474849
Les : nous permettrons de distinguer le nom du numéro de téléphone lors de la lecture de ce fichier.
C'est la méthode readlines que nous allons utiliser pour lire ce fichier. readlines (à ne pas confondre avec readline, sans s) permet de lire l'entièreté du fichier, ligne par ligne, et de stocker chaque ligne dans une liste :
lignes = f.readlines()
Chaque ligne peut alors être utilisée en parcourant la liste :
for ligne in lignes: print ligne
Pour notre exemple, il nous reste à diviser notre ligne en deux, d'un côté des : le nom, de l'autre le numéro de téléphone. Une méthode du type str (chaîne de caractères) permet ça, 'split' :
tab = line.split(":")
La valeur de retour est une séquence, qui contient chacun des éléments de l'explosion de la chaîne de caractère suivant les ':'. Donc si ligne = “tagada:012345678”, on aura tab = [“tagada”, “012345678”].
Une dernière chose : trier la liste des noms par ordre alphabétique. Une méthode de liste existe pour trier : sort(). Par défaut elle trie selon une séquence de caractères, dans notre cas pas très intéressante. En effet, on veut un tri par ordre alphabétique en considérant que 'a' = 'A' (au niveau de l'ordre). Il va falloir définir notre propre fonction de comparaison, en forçant l'utilisation de lettres minuscules. La fonction prend 2 arguments (les 2 éléments à comparer). Elle retourne 1 si arg1 > arg2, -1 si arg2 < arg1, et 0 en cas d'égalité. Par exemple :
def comparaison(arg1, arg2): if arg1.lower() > arg2.lower(): return 1 if arg1.lower() < arg2.lower(): return -1 return 0
Vous remarquerez qu'une fois qu'on retourne quelque chose, la fonction s'arrête.
Donc pour trier une liste avec cette fonction :
une_liste.sort(comparaison)
C'est le nom de la fonction qui est passé en paramètre.