Académique Documents
Professionnel Documents
Culture Documents
2 Types Python 4
2.1 Zoom sur les listes/tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 Fonctions/méthodes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.2 Générer des listes/tableaux . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.3 Illustrations du slicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Matrices, opérations principales . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Zoom sur les chaı̂nes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3 Algorithmique 7
3.1 Test if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.1 Boucles for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.2.2 Boucles while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.3 Théorie des boucles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.3.1 Description d’une boucle : tableaux d’états . . . . . . . . . . . . . . . . . 9
3.3.2 Terminaison d’une boucle while : variants de boucles . . . . . . . . . . . 10
3.3.3 Validité d’une boucle : invariants de boucle . . . . . . . . . . . . . . . . . 11
3.3.4 Complexité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.4 Fonctions def . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.5 Fonctions récursives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.5.1 Exemple 1 : la factorielle . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.5.2 Exemple 2 : la suite de Fibonacci . . . . . . . . . . . . . . . . . . . . . . . 16
• Remarque :
➣(division décimale Python 2.7) ≪ / ≫ ne renverra le résultat attendu QUE si l’un des
acteurs est de type float, ce qu’il faut parfois préciser à Python. Par exemple pour ≪ 5 diviser
par 2 ≫ on tape 5./2 ou 5/2. ou float(5)/2.
➣on peut s’affranchir de cette particularité en validant from future import division qui
passer la division en mode Python 3.
Bl’indexation commence à zéro et pas un donc si truc=’Monty Python’ on accède à ’M’ par
truc[0].
• Remarque :
1 (conversion d’un objet en un autre type) a nouveau=nouveautype(ancien). Exemples :
• Les
matrices peuvent
être vus comme des tableaux 2-d, par exemple :
1 −1 2
M= devient M = array( [ [1,-1,2] ,[1,1,1] ] )
1 1 1
Alors :
➣on accède à l’élément ligne 0, colonne 1 par M[0,1] ou M[0][1] → -1 ;
➣on accède à la première ligne par M[0] → array( [ 1,-1,2] ). Ainsi, le nombre de colonnes
est len(M[0]) ;
➣on accède à la première colonne par M[:,0] → array( [1,1] ). Ainsi, le nombre de lignes
est len(M).
➣Bà la syntaxe du produit matriciel (voir ci-dessous).
3 Algorithmique
• Ceci n’est pas un précis d’algorithmique (il y aura un cours), juste un rappel de la rédaction
globale des principaux éléments d’algorithmiques accompagnés de quelques exemples basiques.
3.1 Test if
• Principe général :
1 if bool :
2 # le test crée une indentation
3 # - >[ instructions à éxécuter si bool == True ]
4 # la fin de l ’ indentation marque la fin du test
5 else : # sinon ( OPTIONNEL )
6 # - >[ instructions à exécuter si bool == False ]
7 # la fin de l ’ indentation marque la fin du else
Typiquement, bool est un booléen (càd une assertion vraie=True ou fausse=False) défini par
une condition de type :
➣a ==b (test d’égalité a ) entre deux éléments de même type ;
➣a !=b (test de différence) entre deux éléments de même type ;
➣a in b (test d’appartenance) pour savoir si a est un élément b de b ;
➣a <=b ou a >=b pour comparer deux éléments qui peuvent l’être ;
➣des liaisons and (et), or (ou), not (négation) entre une ou plusieurs des propositions précédentes.
• Exemple :
1 Exemples de booléens :
1 >>> 1 in [1 ,2 ,3]
2 True
3 >>> 1 in [ [0 ,1] ,[1 ,2] ] # Attention les éléments de cette liste ... sont des
listes
4 False
5 >>> [0 ,1] in [ [0 ,1] ,[1 ,2] ] # ça va aller mieux
6 True
7 >>> " bon " in " bonjour " and not 4 in [1 ,2 ,3]
8 True
9 >>>
a. L’égalité dans un test se rédige par DEUX symboles ≪ = ≫, pas naturel au début et source de beaucoup de
plantages...
b. Pour les str, teste si a est une sous-chaine de b, par exemple "bon" in "bonjour" est True.
3.2 Boucles
• Principe général :
1 for compteur in iterable :
2 # les deux points creent une indentation
3 # - >[ taper les instructions a exécuter pour chaque valeur de l ’ iterable ]
4 # revenir sur l ’ indentation marque la fin de la boucle
1 Typiquement, l’itérable est un ensemble d’entiers [[a ; b]]=range(a,b+1) ou une liste ;
2 Pour parcourir les indices d’une liste, on écrit for compteur in range(len(liste)) :
3 L’instruction break, si elle est rencontrée, provoque une sortie forcée de la boucle ;
• Exemple :
1 afficher a2 pour a dans [[0 ; 4]] :
1 >>> for a in range (5) :
2 print ( a **2)
3
4 0
5 1
6 4
7 9
8 16
Ici, le compteur est a qui décrit l’itérable est la liste range(5)=[0,1,2,3,4] de type liste.
2 Compter a le nombre de ”o” dans ”bonjour” :
1 >>> mot , valeur = ’ bonjour ’ ,0
2 >>> for lettre in mot :
3 if lettre == ’o ’:
4 valeur +=1
5 >>> valeur
6 2
Ici, le compteur est lettre qui décrit l’itérable mot="bonjour" de type str.
a. Peut se faire directement avec la méthode count.
• Principe général :
1 while bool :
2 # les deux points creent une indentation
3 # - >[ instructions a executer tant que bool est True ]
4 # ATTENTION s ’ assurer que bool sera False au bout d ’ un moment ...
5 # ... sinon boucle infinie et plantage .
• Exemple : pour une suite définie par u0 = 0, on définit un+1 = u2n + 1 et on veut déterminer
le plus petit indice n tel que un > 50.
1 valeur , indice =0 ,0
2 while valeur <50: # tant que [ NEGATION DE CE QUE L ’ ON VEUT ]
3 indice +=1
4 valeur = valeur **2+1
5 print ( ’ Rang ’+ str ( indice ) + ’ , suite = ’+ str ( valeur ) )
6 # ce qui suit sera execute en sortie de boucle vu l ’ indentation :
7 print ( ’ Le premier rang ou l on depasse 50 est ’+ str ( indice -1) )
8 # cela donne :
9 Rang 1 , suite = 1
10 Rang 2 , suite = 2
11 Rang 3 , suite = 5
12 Rang 4 , suite = 26
13 Rang 5 , suite = 677
14 Le premier indice ou l on depasse 50 est 4
C’est la variable valeur qui prend les valeurs successives de la suite, à ne pas confondre avec la
variable indice qui joue ici le rôle de n.
• Si l’on étudie une boucle qui affecte certaines variables, on peut faire un tableau d’états
reflétant les valeurs successives de ces variables au cours de la boucle, sur des exemples concrets.
Cela permet d’expliquer et de visualiser des variants/invariants.
Itération k 0 1 2 3 4
qk 0 1 2 3 4 → sortie de boucle après 4 itérations car r4 < b
rk 43 33 23 13 3
Au cas où l’on n’aurait pas compris... Les variables q,r qui, en sortie de boucle, valent q4 =
4, r4 = 3 sont comme par hasard le quotient/reste de la division euclidienne de a = 43 par
b = 10...
• On doit s’assurer qu’une boucle while finit toujours par s’arrêter b . Pour cela, on essaie d’isoler
un variant de boucle , càd une quantité ≪ de type entier ≫ :
➣ qui reste positive tant qu’on est dans la boucle ;
• Remarque : sans être un entier, un variant de boucle peut être plus largement un booléen :
est facile, il s’agit de la quantité r-b dont la positivité est toujours vraie dans la boucle, et qui
décroit strictement (de b>0) à chaque itération.
• Remarque : on peut aussi rédiger avec les notations de la partie précédente, en observant
que
0 6 rk 6 a − k · b
dans la boucle, avec le membre de droite strictement négatif à partir d’un certain rang, qui
provoque la sortie.
a. Par convention, q0 , r0 sont les valeurs avant d’entrer dans la boucle.
b. Sinon, on parle de boucle infinie → plantage du programme et chauffage des processeurs :(
• Un invariant de boucle est égalité ou plus largement une propriété qui est :
➣ vraie avant l’entrée dans la boucle (initialisation) ;
Itération k 0 1 2 3 4
qk 0 1 2 3 4
rk 43 33 23 13 3
b · qk + rk 43 43 43 43 43
P (k) = [b · qk + rk = a]
➣vraie pour k = 0 ;
➣si P (k) est vraie, à l’itération d’après si elle a lieu :
qk+1 = qk + 1 P (k)
=⇒ b · qk+1 + rk+1 = b · qk + b + rk − b = a
rk+1 = rk − b
D’où la preuve de l’invariant par réccurence et, en sortie de boucle comme on a 0 6 rk < b et
toujours :
a = qk · b + rk ,
les valeurs de q,r en sortie de boucle sont bien celles de la division euclidienne.
3.3.4 Complexité
• Remarque : nous abordons la notion de complexité en temps a au niveau des boucles, mais
elle s’étudie pour tout type d’algorithme.
• Remarque : r+=1 (incrémentation) est comptée comme 1 opération élémentaire a alors que
r=r+1 compte b
• Evaluer la complexité d’un algorithme c’est évaluer, ligne par ligne, le nombre d’opérations
élémentaires nécessaire pour mener à bien sa tâche, tout en étant conscient :
➣qu’il faut prévoir le pire des cas (en cas de test par exemple) ;
➣que les lignes présentes dans les indentations de boucles interviendront autant de
fois qu’il y aura d’itérations, et qu’il faut donc toujours essayer de prévoir le nombre de ces
itérations.
• Les résultats seront donnés sous forme de O(données) (≪ grand O ≫), càd du type cte× données
sans chercher détailler la constante (on la majore par la pire situation), on parle (du meilleur
au pire) :
➣de complexité logarithmique si on a un O(données) = cte × ln(données) ;
➣de complexité linéaire si on a un O(données) = cte × données ;
➣de complexité quadratique si on a un O(données2 ) = cte × données 2 ;
➣de complexité exponentielle si on a un O(exp(données)) (le pire des trois).
• Exemple :
1 Calculer une puissance bn :
1 def puissance (b , n ) :
2 res =1
3 for i in range ( n ) :
4 res = res * b
5 return res
On a :
➣1 assignation ligne 2 ;
➣[1 assignation + 1 calcul ligne 4] ×n (boucle ligne 3).
En conclusion, on a une complexité c 2 + 2n = O(n) (linéaire).
2 Compter le nombre de 1 dans une matrice n × n :
1 def compter ( M ) :
2 resultat =0
3 for i in range ( n ) :
4 for i in range ( n ) :
5 if M [ i ][ j ]==1:
6 resultat +=1
7 return resultat
On a :
➣1 assignation ligne 2 ;
a. Modification in place : directement dans la case mémoire pointée par r sans création d’une nouvelle.
b. Doit créer une nouvelle case mémoire pour faire le calcul, et refait pointer r vers cette nouvelle case : c’est
à la fois plus lent et surtout, plus gourmand en mémoire que la modification in place.
c. Peut être grandement améliorée par l’algorithme d’exponentiation rapide.
On a :
➣2 tests lignes 2 et 3 ;
➣2 assignation ligne 4 :
➣[1 test ligne 5 + (1 calcul + 1 assignation ligne 6) + 1 incrémentation ligne 7] ×k
itération, avec k à estimer en fonction des données a,b.
• Remarque : avec les notations de la partie 3.3.1 page 9, on peut montrer par récurrence
que rk = r0 − kb = a − kb et que :
a
➣à l’itération k de sortie rk < b =⇒ < k + 1 ;
b
a
➣donc à l’itération d’avant rk−1 > b =⇒ > k.
b
a
Ainsi : k 6 < k + 1 donc k = E[a/b] (partie entière) et, à l’arrivée une complexité de
b
4 + 4E[a/b] = O(E[a/b]).
• Principe général.
1 >>> def nom_fonction ( entrees ) :
2 # les deux points créent une indentation
3 # - >[ instructions à exécuter ]
4 # la procédure s ’ arr^
e te au premier return
5 return ( sortie )
résultat
• Remarque :
1 Ble programme sort de la fonction dès qu’il tombe sur un return, ce qui peut donner
des surprises s’ils sont mal placés dans les indentations ;
• Exemple :
1 Fonction f définie par :
➣Entrée : une variable x ;
➣Sortie : la valeur x+1.
1 >>> def f ( x ) : # Ici l ’ entrée se résume à une variable x
2 return ( x +1) # Ici la sortie se résume à une variable ( contenant x +1)
3
4 >>> f (4)
5 5
• Remarque : vu sa sortie, cette fonction est dite booléenne et peut intervenir dans un
test, par exemple dans un ≪ if test(liste): ≫.
3 Fonction recherche définie par :
➣Entrées : deux chaı̂nes de caractères mot et lettres ;
➣Sortie : la liste (éventuellement vide) des indices i où la lettre i de mot vaut lettre.
1 >>> def recherche ( mot , lettre ) : # ici deux entrées
2 sites =[] # liste vide
3 for indice in range ( len ( mot ) ) : # pour parcourir tous les indices
4 if mot [ indice ]== lettre :
5 sites . append ( indice ) # on rajoute l ’ indice à
6 # la liste des sites
7 return ( sites ) # la procédure s ’ arr^e te , avec sortie = sites
8
9 >>> recherche ( ’ marseille ’ , ’e ’)
10 [4 , 8]
11 # oui il y a bien un e aux emplacements 4 et 8
• Un algorithme est dit itératif quand il répète un groupe d’instruction un certains nombre de
fois, elle est en général basée sur une boucle for ou while.
• Il est dit récursif s’il s’appelle lui-même avec d’autres entrées pendant son exécution, pos-
sibilité offerte par tous les langages évolués. Dans l’esprit, il est adapté à toute propriété
mathématique se prouvant par récurrence. A noter que la récursivité n’exclut pas l’itérativité
(on peut avoir des boucles dans une structure récursive).
• En général : la simplicité a est du côté du récursif mais la complexité en temps du côté itératif.
• Les algorithmes récursifs posent les mêmes problèmes que les algorithmes classiques : Des-
cription (les arbres d’appel remplacent les tableaux d’état), terminaison, validité, complexité :
les preuves par récurrences sont naturellement adaptées à ces questions théoriques sur les pro-
grammes récursifs.
• Deux versions, l’une itérative, l’autre récursive, de l’implémentation d’une fonction factorielle :
1 def facto_iterat if ( n ) :
2 res =1
3 for i in range (2 , n +1) :
4 res *= i
5 return res
6
7 def facto_recurs if ( n ) :
8 if n ==1: # Initialisatio n
9 return 1
10 else :
11 return n * facto_recurs if (n -1) # Heredite
➣Description :
on peut écrire que :
ou alors on peut représenter graphiquement les appels par un arbre d’appels partant d’une
entrée donnée (par ex. 4) pour décrire les appels successif (pour simplifier, fr=fonction recursive) :
profondeur d’appel
3x2x1 2x1 1
1 # iteratif
2 def fibo_i ( n ) :
3 if n ==0 or n ==1:
4 return 1 if n ==1 else 0
5 else :
6 a , b =0 ,1 # a joue le role de u_n , b joue le r A~ ´le de u_n +1
7 for i in range (n -1) :
8 a , b =b , a + b # assignation multiple
9 return b
10
11 # recursif
12 def fibo_r ( n ) :
13 if n ==0: # initialisatio n
14 return 0
15 elif n ==1:
16 return 1 # initialisati on
17 else :
18 return fibo_r (n -1) + fibo_r (n -2) # Heredite
• On s’aperçoit sur l’exemple étudié de l’avantage du récursif : simplicité d’écriture, clarté (même
si la possibilité d’assignations multiples allège bien la version itérative)
2+1=3
fr(3)+fr(2)
1+0
1+1
fr(2)+fr(1) fr(1)+fr(0)
1 0
1+0 1
return 1 return 0
c’est à dire que dans ce cas la suite (C(n))n des complexités est-elle même une suite de Fibonacci.
le cours b nous apprend qu’il existe x, y, z constantes telles que :
√ !n √ !n √ !n
1+ 5 1− 5 1+ 5
C(n) = x · +y· +z ∼x· = x · exp(n · cte)
2 2 2
On remarque que la complexité est géométrique, càd exponentielle, ce qui est énorme.
➣Validité, se fait par récurrence en notant P (n) : [l’appel sur n donne bien le résultat attendu]
sur deux rangs, avec :
Initialisation : P (0) et P (1) vrais.
Hérédité : supposons P (n) et P (n + 1) on obtient P (n + 2).
• Remarque : on peut comparer les efficacités des deux programmes en comparant les temps
d’exécution, grâce au module time :
a. HP
b. Le programme ne permet pas de traiter la relation avec z 6= 0, mais dans ce cas l’idée et qu’une solution est
la somme : d’une solution homogène (càd avec z = 0 : couvert par le cours) + une solution particulière (cherchée
sous la forme d’une constante qui va bien).
1.4
1.2
temps iteratif/temps recursif
1.0
0.8
0.6
0.4
0.2
0.0
2 3 4 5 6 7 8 9
n
On voit que l’itératif devient très vite + rapide que le récursif (complexité linéaire vs. complexité
exponentielle).
• Un exemple plus subtil, où la structure récursive ne se découvre que dans l’analyse du
problème.
• Soit n dans N∗ . On appelle une n-partition toute liste d’entiers non nuls [u1 , . . . , up ] telle que :
p
X
n= ui .
i=1
On souhaite implémenter une fonction partition qui, à une entrée n, renvoie la liste des n-
partitions, par exemple partition(3) doit retourner :
• Une maladresse possible en récursivité est de déclencher plus d’appels récursifs que nécessaire,
augmentant inutilement la complexité.
• Les deux codes qui suivent, destinés à retourner le n-ième terme d’une suite récurrente définie
par u0 = 1 et :
∀n dans N∗ , un = un−1 exp(−un−1 ),
semblent analogues pourtant leurs complexités n’ont rien à voir :
1 def code1 ( n ) :
2 if n ==0:
3 return 1
4 else :
5 return code1 (n -1) * exp ( - code1 (n -1) )
6
7 def code2 ( n ) :
8 if n ==0:
9 return 1
10 else :
11 c = code2 (n -1)
12 return c * exp ( - c )
• Ainsi, il vaut mieux stocker le résultat d’un appel récursif dans une variable (coût=une
opération élémentaire) plutôt que l’appeler plusieurs fois (coûts= BIG)...
• Un des principaux problèmes en informatique est le stockage des données avec un choix per-
manent entre deux structures de données classiques :
➣la structure de tableau=array : les données sont stockées dans un tableau tab de taille a fixe,
on peut consulter/modifier à tout moment n’importe quelle donnée en appelant tab[i].
➣la structure de pile=stack : on stocke des données dont le nombre est variable, en ne s’autorisant
que deux actions :
⊲ push(L,X) : empiler la donnée L à la fin de la pile L ;
⊲ pop(L) : dépiler, càd enlever le dernier élément de la pile L.
push(L,X)
a g z t X
push 0 1 2 3 4
L
a g z t
0 1 2 3
pop pop(L) valeur du pop
a g z t
0 1 2
• Remarque : chaque appel de ces commandes provoque une modification in place de la pile.
• L’analogue de la structure de pile est une pile d’assiette : on ne peut qu’ajouter une assiette
ou enlever la dernière. Les anglais parlent de LIFO = Last In, First Out.
➣Avantage des tableaux : un accès rapide à toutes les données ;
➣Avantage des piles : rapidité et simplicité d’accès dans tout problème de stockage privilégiant la
dernière information dans l’historique : fonctions undo/redo dans un éditeur, étude d’un problème
de parenthésage (voir section 3.6.4 page 21) ou recherche d’un chemin dans un labyrinthe par
exemple.
• Concrètement, nous stockerons tableaux et piles dans le même type list de Python.
a. Python autorise cependant des ≪ tableaux de taille variable ≫ avec le type list.
• Nous voulons rédiger une fonction parenthesage(mot) qui, pour un argument mot comme
ci-dessus retourne :
➣False si l’on n’a pas un bon parenthésage (sinon True) ;
➣affiche les tuples (j,i) correspondant aux sites (ouvrante,fermante) associés.
012 34 5
Ainsi, parenthesage("( ( ) ( ) )") doit afficher (1,2),(3,4),(0,5) puis True.
• Nous allons parcourir mot en faisant évoluer une pile L au début vide :
➣où l’on empilera les sites où il y a des ouvrantes ;
➣que l’on dépilera à chaque site où il y a une fermante, en renvoyant un affichage.
Ceci donnerait avec par exemple "(()())" le tableau d’états :
Voici l’implémentation :
1 def parenthesage ( mot ) :
2 L =[]
3 i =0
4 for i in range ( len ( mot ) ) :
5 if mot [ i ]== " ( " :
6 push (L , i ) # on empile les sites ou il y a des ouvrantes
7 else : # dans ce cas on est sur un site avec une fermante
8 if L ==[]: # s ’ il n ’y a plus d ’ ouvrante a refermer
9 return False
10 else :
11 print ( pop ( L ) ,i ) # on depile et on affiche le couple site
ouvrant , site fermant
12 i +=1
13 if not testvide ( L ) : # s ’ il reste des ouvrantes non refermees
14 return False
15 else :
16 return True
C’est un exemple où seule le sommet de la liste est intéressant, d’où la programmation utilisant
les fonctions primitives sur les piles.
3.7 Tris
• Une requête SQL classique se présente sous la forme SELECT ...(3) FROM ...(1) WHERE
...(2)
➣Le champ (1) du FROM se complète en premier en répondant à la question suivante : dans
quelles relations sont les attributs dont j’ai besoin ?
➣Le champ (2) du WHERE se complète ensuite en répondant aux questions : ai-je des condi-
tions sur les valeurs d’attributs exprimées dans ma requête ? ai-je plusieurs relations
dans ma clause FROM ? Si oui, quelles sont les conditions de jointure(s) ? Si toutes
les réponses sont négatives la clause WHERE n’apparaitra pas.
➣Enfin le champ (3) du SELECT se complète en dernier en répondant à la question : quel
résultat souhaite voir l’utilisateur (schéma du résultat) ?
• Domaines. Les domaines utilisés dans les bases de données sont conformes aux types classi-
quement utilisés dans les langages de programmation, à savoir :
• Entier : INTEGER
• Décimal : DECIMAL (m,n)où m est le nombre de chiffres et n le nombre de chiffres après la
virgule. Ainsi DECIMAL(4,2) peut représenter des chiffres comme 99,99
• Réel flottant : FLOAT
• Chaı̂ne de caractères : CHAR (n) et VARCHAR(n). Les CHAR font systématiquement n
caractères (les chaı̂nes plus courtes sont complétées par des espaces, les VARCHAR sont
taillés au plus juste dans la limite des n caractères
• Date : DATE (dans la norme SQL2 !). Ce type normalisé très tard possède une manipulation
sensible. Il faut bien connaı̂tre le format d’expression de la date et sa langue.Le 1er janvier
2010 peut par exemple s’exprimer en ’2010-01-01’ ou ’01-JAN-2010’ ou ’1/1/10’ ...
• il n’y a pas de type booléen en SQL2
• Création d’un schéma de relation. L’ordre de création de relation minimale suit la syntaxe
suivante :
CREATE TABLE Nom
( Attribut 1 Type,
...,
Attribut N Type) ;
• Remarque : pour une matrice aléatoire, on génère d’abord une liste que l’on reshape (voir
section 2.1.2 page 5).
4.2 Tracés 2d
a
from matplotlib.pyplot import ∗
• Remarque :
1 typiquement (voir exemple ci-dessous) la liste des abscisses est générée comme dans la
section 2.1.2 page 5, avec un linspace et celle des ordonnées est une λ-fonction de la
première ;
2 Bles graphiques ne s’affichent qu’à la commande show().
Commandes Syntaxe
Générer une légende axe des x (ou y) xlabel("texte")
Générer une grille grid()
Générer une ligne brisée de sommets plot(list abscisses,list ordonnées,options)
d’abscisse/ordonnées connues voir plus bas pour les options de tracé
Générer un tracé de y = f (x) sur x dans [a, b] x=linspace(a,b,20)
discrétisé à 20 points plot(x,f(x),options)
Réglages axes axis([xmin,xmax,ymin,ymax])
Afficher les tracés show()
Histogramme d’une liste liste hist(liste)
Vider les tracés générés clf() (clear figure)
• Options de tracé :
a. Des fonctions/types présentées dans ce document font partie de ce module qu’il faudra charger. La syn-
taxe présentée active automatiquement les fonctions/types. En cas de problème, on pourra toujours taper
import matplotlib.pyplot as pl, np étant une abréviation arbitraire. Les fonctions/types associés devront
impérativement être précédées du préfixe pl, par exemple plot deviendra pl.plot.
• Un petit exemple :
1 # -* - coding : utf -8 -* -
2
3 from numpy import *
4 from matplotlib . pyplot import *
5 f = lambda x : sin ( x ) # declaration fonction
6 # #### BEL EMPLACEMENT DE LEGENDES
7 legend ( loc =0)
8 # #### LEGENDES SUR LES AXES
9 xlabel ( " x " )
10 ylabel ( " y " )
11 # #### GENERATION D ’ UN TRIANGLE A (0 ,0) ,B ( pi ,0) ,C ( pi /2 ,1)
12 absc =[0 , pi , pi /2 ,0]
13 ordo =[0 ,0 ,1 ,0]
14 triangle = plot ( absc , ordo , linestyle = " dashed " , marker = " o " , label = " Triangle " )
15 # #### GENRATION y = f ( x )
16 abscisses = linspace (0 ,2* pi ,50) # discretisati on A~ 50 pts
17 ordonnees = f ( abscisses ) # generation ordonnees
18 graphe_sinus = plot ( abscisses , ordonnees , linewidth = " 3 " , label = " sinus " )
19 # #### ET MAINTENANT ON AFFICHE
20 show ()
donne :
Bil y a parfois un bug sur la donnée des chemins ; par exemple "C:\Users\Documents\" peut
poser problème. L’explication est que le groupe \U est une commande reconnue et automatique-
ment executée par l’éditeur/encodeur (qui bugge car elle est hors-propos). Le bug se résout en
rajoutant un ≪ r ≫ au début du chemin, en l’ocurrence en changeant en :
r"C:\Users\Documents\"
• On commencera tous les documents par l’en-tête chargeant les modules nécessaires :
1 from numpy import *
2 from pylab import *
3 import os # module gerant le repertoire
4 from skimage import * # module gerant les images
5 from skimage import io # module permettant de gerer les niveaux de gris
6
7 os . chdir ( " mettez l ’ adresse de votre repertoire " ) # modifie le repertoire courant
8 # si la ligne precedente bugge , mettez un r devant l ’ adresse
9 # par exemple " C :\ User [...]" devient r " C :\ User [...]
a. Sur la bibliothèque PIL la plus connue, l’intensité est un entier variant de 0=noir à 255=blanc.
1 1
i 2
3 3
4 4
dx tab[0,4]=0.5
tab=ones((5,5)) tab[2:4,1:4]=0
➣En couleurs. Même principe, mais la couleur de chaque pixel tabi,j est une liste [R,G,B] =
intensité Red/Blue/Green dans [0,1]. Pour créer un tel tableau de taille dx × dy, par exemples
remplis de pixels blancs = [1,1,1], on utilise tab=ones((dx,dy,3)).
Le format d’un tableau tab par tab.shape, dans l’exemple ci-dessus on obtiendra (5,5).
0 1 2 j 4 0 1 2 3 4
dy dy
0 0
1 1
i 2
3 3
4 4
dx tab[0,4]=[0,0,1]
tab=ones((5,5)) tab[2:4,1:4]=[1,0,0]
L’affichage peut se faire à tout moment avec imshow(tab) mais BPython a tendance à faire des
fondus d’affichages entre les pixels voisins, qui peuvent mener à bien d’autres figures que celle
que vous attendez. On annule ces corrections via imshow(tab,interpolation="nearest").
0 j
dy
dx
[x, y, z] avec x,y,z intensités RGB dans [0, 1]
tab[i, j] = ou
x dans [0, 1] : intensité de gris
• Remarque :
1 immédiatement demander tab.shape pour voir le format dx × dy de l’image, et si elle est
codée en couleurs ou pas ;
2 il est souvent commode de créer une copie indépendante du tableau initial pour le modifier,
via copie=copy(tab) ;
3 après modification, on sauvegarde le résultat avec savefig("nom que vous voulez.png").
• Commandes utiles :
a. C’est la seule extension qui marchera sur toutes les machines, mais normalement tous les formats sont
accessibles.
• Principe général d’un traitement d’image connue sous forme d’un tableau tab. En
général, mais ce n’est pas obligatoire :
1 on repère le format dx,dy=tab.shape[0:2] ;
2 on crée une copie copie ;
3 on parcourt la copie à l’aide de deux boucles imbriquées, en modifiant copie[i,j] ;
4 on retourne et/ou on affiche copie dans le mode désiré.
• Exemple : floutage d’une image. Nous travaillons, pour simplifier, avec des images en
niveaux de gris. L’idée du floutage est de :
➣travailler sur une copie copie de l’image tab ;
➣remplacer l’intensité de chaque pixel copie[i,j] par la somme des intensités immédiatement
voisines + la sienne, toutes pondérées par 1/9 pour en faire la moyenne : la matrice 3x3 associée
est appelé filtre du traitement d’image.
tab copie
50
100
150
200
250
300
350
Le floutage donne :
50
100
150
200
250
300
350
• Voici un exemple de definition d’une classe ≪ vecteurs ≫, dont les instances (=représentants)
ont trois attributs : abscisse, ordonnée et nom.
1 class vecteur : # nom de la classe
2
3 def __init__ ( self ,a ,b , c ) : # " methode constructeur " : self designe l ’
instance de la classe ( non negociable ) , ici d A~
finiec par trois attributs
notes arbitrairem en t a , b , c
4 self . coord = [a , b ] # creation d ’ un attribut " coord "
5 self . nom = c # nomination du troisieme
6
7 def __repr__ ( self ) : # " methode representati on "
8 return " Vecteur " + self . nom + " =[ " + str ( self . coord [0]) + " ," + str ( self . coord
[1]) + " ] " # le retour doit etre une str
9
10 def scalaire ( self , t ) : # methode speciale modifiant les attributs de l ’
instance self en argument
11 self . coord [0]= self . coord [0]* t # modification de la premiere coordonnee
12 self . coord [0]= self . coord [0]* t # modification de la seconde
13 # pas besoin de retour
14
15 def somme ( self , self2 ) : # methode speciale construisant une instance de la
classe sans modifier les instances appelees
16 x , y = self . coord
17 n = self . nom
18 xp , yp = self2 . coord
19 np = v . nom
20 return vecteur ( x + xp , y + yp , n + " + " + np ) # retour d ’ une instance
21
22 u= vecteur (1 ,2 , ’u ’) # exemple creation d ’ une instance de la classe vecteur
23 u # provoque l ’ appel de la methode de representati o n
24 u. scalaire (2) # exemple d ’ application d ’ une methode speciale a l ’ instance
BLes méthodes spéciales à une classe doivent être appelées avec le nom de la classe en préfixe
càd que pour une instance v de la classe vecteur :
➣Python ne comprendra pas scalaire(v,2) pour appliquer une méthode spéciale à la classe ;
➣mais vecteur.scalaire(v,2) ;
➣autre syntaxe acceptable : v.scalaire(2).