TD01 td1
TD01 td1
TD01 td1
INF TC1
Ve i e
2020-2021
o
o
Introduction #4
III Introduction
• Python est un langage de programmation à la fois impératif, fonctionnel et objet avec un typage dynamique. Dans
Python, toute est expression et toute expression représente une valeur (que l’on peut stocker / affecter / écrire / ...
ou pas).
• Penser à utiliser la fonction help pour connaitre les détails d’une fonction : par exemple help(’print’) ou
print? (ou encore print??)
• Si vous travaillez sans un IDE (éditeur avec interprète de Python intégré), préférez IPython à l’interprète de base
de Python. IPython fournit des outils supplémentaires ainsi qu’un accès au système hôte (Windows, Linux, MacOS,
etc).
"""
On peut a u s s i c r é e r un commentaire l o n g = une zone de
commentaires s u r p l u s i e u r s l i g n e s p l a c ées
e n t r e une p a i r e de t r i p l e g u i l l e m e n t s dont l e second s u i t :
"""
+ Remarques :
• Un ’ ;’ à la fin d’une ligne rend la ligne muette (pas d’affichage des résultats). Il permet également de placer plusieurs
expressions sur la même ligne.
• Si vous placez un commentaire immédiatement après la signature d’une fonction (ou une méthode, une classe, etc.)
entre un couple de """, votre commentaire (appelé docstring) devient accessible avec help :
• Python est un langage à indentation : un bloc est une zone contigüe de lignes d’expressions avec la même inden-
tation. Un tel bloc peut en contenir d’autres.
Ÿ Essayer d’utiliser la même indentation partout (espaces ou tabulation). Une mauvaise indentation qui ne provoque
pas d’erreur de syntaxe est un piège parfois difficile à détecter.
Exemples et exercices simples #5
Points Python :
input
Conversion en int.
print
Affectation (=)
a= i n t ( i n p u t ( ’ Donner l e c o e f f i c i e n t a : ’))
b= i n t ( i n p u t ( ’ Donner l e c o e f f i c i e n t b : ’))
c= i n t ( i n p u t ( ’ Donner l e c o e f f i c i e n t c : ’))
i f ( a == 0 ) :
i f ( b != 0) :
p r i n t ( " Pas q u a d r a t i q u e : r a c i n e s i m p l e x = " , c / b )
else :
p r i n t ( " une blague ! " )
else :
d e l t a =b * b 4*a * c #ou b * * 2
i f ( d e l t a < 0) :
p r i n t ( " pas de r a c i n e s r e e l l e s " )
else :
assert ( a != 0) # Dé j à vé r i f i é mais pour montrer l ’ i n t é r ê t de " a s s e r t " .
i f ( d e l t a >0) :
x1 = ( b+math . s q r t ( d e l t a ) ) / ( 2 * a )
x2 = ( b math . s q r t ( d e l t a ) ) / ( 2 * a )
p r i n t ( " x1 = " , x1 )
p r i n t ( " x2 = " , x2 )
else :
x1 = x2 = b / ( 2 * a )
p r i n t ( " r a c i n e double x1 = x2 = " , x1 )
• Après un ’ :’ (d’ouverture d’un block), si vous passez à la ligne, n’oubliez pas l’indentation.
Points Python :
import
structures conditionnelles if-else, if-elif-else, assert
indentation (préférez des espaces à la tabulation) : espaces ou tabulation, utilisez la même chose dans un bloc !
test et comparaisons (==, !=, < , >, >=, <=, ...)
math.sqrt()
+ Remarques :
• Contrairement aux versions antérieures à Python 3, le résultat de l’opérateur ’/’ est un réel. Pour récupérer la
partie entière d’une division, utiliser ’//’ (ou convertir le quotient en un entier).
• La notation math.sqrt(delta) : pour éviter de mentionner math, remplacer
import math; par
from math import sqrt; (voir aussi plus loin à propos des modules)
Introduction aux fonctions #6
# Partie Principale
a= i n p u t ( ’ Donner l a v a l e u r de a : ’ )
b= i n p u t ( ’ Donner l a v a l e u r de b : ’ )
p r i n t ( ’ l a moyenne = ’ , moyenne ( i n t ( a ) , i n t ( b ) ) )
+ Remarques :
• Une fonction Python peut renvoyer différents types de données : il n’y a pas de contrôle (n’en déplaise aux
Camliens !).
• Dans le cas présent, on décide de renvoyer un string (au lieu de float ou string).
• Savoir quel type de donnée une fonction doit renvoyer
Z est davantage nécessaire si ce résultat doit participer à
X
une expressions (P. ex. une expression effectuant ou sur la fonction quadratique).
• Pour répondre à de telles situations en Python, le mécanisme d’exception permet de définir des fonctions partielles
(comme quadratique) qui s’appliquent sous certaines conditions, voir la section XVI page 30.
• Écrire la fonction moyenne comme ci-dessus et utiliser cette fonction pour calculer l’écart type via la variance =
moyenne((xi µ)2 ) d’une suite de nombres telle que la liste echantillon ci-dessus.
Ÿ Vous devez donc appeler moyenne avec une liste qui contient les (xi µ)2 , xi 2 echantillon.
+ Naturellement, vos résultats doivent (plus ou moins) s’accorder avec N (16, 2).
• Voir les tirages aléatoires en section XVII, page 33 et les listes en compréhension en section XXIV, page 52.
Créer un script Python indépendant #7
• Écrire le code Python nécessaire pour calculer l’écart type de cette seconde manière (réutilisez moyenne() ci-
dessus) et vérifier bien que le résultat correspond au calcul précédent.
Pour commencer, on place le code vu ci-dessus dans le fichier racines.py. Pour les besoins de l’exemple, on sim-
plifie le code en prenant moins de précautions au niveau des coefficients (car on maîtrise les arguments d’appel).
# Partie Principale
print ( trinome ( 1 . 0 , 3.0 , 2 . 0 ) )
print ( trinome ( 1 . 0 , 2.0 , 1 . 0 ) )
print ( trinome ( 1 . 0 , 1.0 , 1.0) )
Sous Windows : exécuter votre code dans une fenêtre de commande par python.exe racines.py
Windows ne semble pas avoir le mécanisme shebang (à moins d’avoir installé cygwin)
• Complétons en nous donnant les moyens d’importer nos propres fonctions pour les utiliser dans d’autres codes.
1. Valeur absolue : la variance et l’écart type sont toujours 0. Dans leur formulation usuelle, ce problème n’apparaît pas grâce à (xi µ)2
Créer un script Python indépendant #8
(1 , 1.0) # I l nous f a u t j u s t e c e c i
• Le problème est que la partie principale de racines.py s’exécute aussi ! Et ce n’est pas ce que l’on veut.
• Résumons :
Nous voulons être capables de tester nos fonctions placées dans racines.py,
Nous voulons pouvoir lancer ce fichier comme un programme exécutable indépendant,
Nous voulons également réutiliser les dites fonctions dans d’autres programmes Python (comme nous l’avons
fait dans utiliser_racines.py
• Cela donne ("assert" oubliés car on sait comment on appelle cette fonction depuis "main" ) :
from math i m p o r t s q r t ;
# fonction
def trinome ( a , b , c ) :
delta = b**2 4*a * c
i f delta > 0.0:
racine_delta = sqrt ( delta )
r e t u r n ( 2 , ( b r a c i n e _ d e l t a ) / ( 2 * a ) , ( b+ r a c i n e _ d e l t a ) / ( 2 * a ) )
e l i f delta < 0.0: return (0 ,)
else : return (1 , ( b / ( 2 * a ) ) )
OU (sous Windows) :
python r a c i n e s . py
• On peut maintenant importer notre fonction dans utiliser_racines.py ci-après sans que la partie principale
de racines.py ne s’exécute :
from r a c i n e s i m p o r t t r i n o m e ;
p r i n t ( trinome ( 2 . 0 , 4.0 , 2 . 0 ) )
+ La lettre ’j’ ou ’J’ est utilisée pour la partie imaginaire d’un nombre complexe. Pourquoi pas ’i’ ou ’I’ ? : les concep-
teurs de Python ont suivi les symboles utilisés en Ingénierie où ’I’ est déjà utilisé comme symbole du courant.
VII-1 Exemples
i f t y p e ( 1 ) i s n o t i n t : p r i n t ( ’ oups ’ )
i f type ( ’ 1 ’ ) i s not i n t : p r i n t ( 1 )
type ( 3 . 1 4 )
# float
t y p e ( None )
# NoneType
• Pour connaître les détails des types et leurs limites (les tailles sont en byte = 2 octets en Python) :
i m p o r t sys ;
p r i n t ( sys . i n t _ i n f o )
# sys . i n t _ i n f o ( b i t s _ p e r _ d i g i t =30 , s i z e o f _ d i g i t =4)
p r i n t ( sys . f l o a t _ i n f o )
# sys . f l o a t _ i n f o ( max=1.7976931348623157e+308 , max_exp=1024 , max_10_exp=308 , min =2.2250738585072014e 308,
min_exp= 1021, min_10_exp= 307, d i g =15 , mant_dig =53 , e p s i l o n =2.220446049250313e 16, r a d i x =2 , rounds =1)
p r i n t ( sys . g e t s i z e o f ( f l o a t ) ) # La t a i l l e de la classe f l o a t
# 400
p r i n t ( sys . g e t s i z e o f ( f l o a t ( ) ) ) # La t a i l l e d ’ un f l o a t
# 24 # Ce que coute en o c t e s un r é e l ( v a l e u r + i n f o s supplémentaires )
str1
# ’123 ’
Ici, la fonction join() va accoler les éléments de son paramètre et les mettre à la que leu-leu. La chaîne vide (”) placée
à gauche de join() sera le séparateur à placer entre les éléments accolés (ici rien).
• entiers en string : liste d’entiers en string : on convertie chaque entier en caractère (car join() s’applique aux
strings) puis
list1 = [ 1, 2, 3]
str1 = ’ ’ . join ( str (e) for e in l i s t 1 ) # ou avec " " à l a p l a c e de ’ ’
str1
# ’123 ’
• string en entier : pour convertir un string S composé de chiffres en un entier, int(S) suffit. Par contre, si on n’est
pas certain que les caractères de S sont des chiffres, un contrôle est nécessaire (voir exercice ci-dessous).
• string en réel : pour convertir un string S composé de chiffres en un réel, float(S) suffit. Cependant, la même
précaution que pour les entiers ci-dessus s’applique.
a = " 545.2222 "
float (a)
# 545.2222 s u i v a n t l e s y s t ème, on peut a v o i r des ’ 0 ’ apr ès l e s ’ 2 ’
VIII-2 Exercice
• Écrire la fonction convertir(S) qui convertit son paramètre (un string) en un entier. Pour que la conversion soit
possible, le paramètre S doit être être composé de chiffres éventuellement précédé d’un signe.
Noter qu’on peut accéder à S[i] (i commence à 0)
+ Si un string S ne contient que des chiffres : S.isdigit() est vrai.
VIII-3 Exercice
• Écrire la fonction convertir2r(S) qui convertit son paramètre (un string) en un réel (loat). Pour que la conversion
soit possible, le paramètre S doit être être éventuellement précédé d’un signe, puis composé de chiffres suivis d’un
’.’ puis une série de chiffres. La présence d’un ’.’ est obligatoire, et qui est forcément suivi d’au moins un chiffre.
+ On peut réutiliser la fonction définie ci-dessus.
Modules Python #11
IX Modules Python
• Format général :
import tel_module
t e l _ m o d u le . f o n c ( . . ) # appel de l a f o n c t i o n f o n c du module
• Mieux conseillé :
i m p o r t t e l _ m o d u l e as mod1
i m p o r t un_module as mod2
mod1 . f o n c ( . . ) # appel de l a f o n c t i o n f o n c du t e l _ m o d u l e
mod2 . f o n c ( . . ) # appel de l a f o n c t i o n homonyme du un_module
d e f ma_fonction ( ) :
localname = t e l _ m o d u l e . f o n c
f o o = localname ( bar )
• Un compromis intéressant : on peut renommer les fonctions importées pour éviter les conflits de noms :
from sys i m p o r t argv as sys_argv
X La fonction range
• Format de la fonction range() :
range([début], fin, [incrément])
Ÿ Le début et l’incrément sont optionnels (mis entre []).
Ÿ Si on donne deux arguments à range(), ce seront alors le début et la fin de l’intervalle (et l’incrément=1).
l i s t (R)
# [ 0, 1, 2, 3]
R. index ( 2 ) # L ’ i n d i c e de ’ 2 ’ dans R
# 2
4- Dans range(debut, fin), on a en général debut < f in tandis qu’avec debut f in, on désigne un intervalle
vide (et non une erreur).
l i s t ( range ( 1 , 1 ) )
# []
• Les constantes multiplicatifs peuvent être insérées ou être sortie des sommes :
Xn n
X
c. f (i) = c.f (i) car c(f (m) + · · · + f (n)) = c.f (m) + · · · + c.f (n).
i=m i=m
n
X n
X n
X
• Associativité : sachant que f (i) + g(i) = (f (i) + g(i)), on peut écrire en Python :
i=m i=m i=m
sum(f(i) for i in S) + sum(g(i) for i in S)
qui est la même chose que sum(f(i) + g(i) for i in S).
Ÿ Notons que ces équivalences ne tiennent que si les fonctions en questions n’ont pas d’effet de bord (ne modifient
pas la mémoire).
XI Les listes
• Une introduction par des exemples de quelques fonctions sur les listes.
• Le premier élément d’une liste L est à l’indice 0,
le dernier à l’indice len(L)-1 ou à l’indice -1 et L[-2] = L[len(L)-2]).
• Quelques fonctions (pour une liste L), voir les autres fonctions plus loin :
L[:] toute la liste L (référence explicite aux éléments de L, cf. la copie d’une liste)
L[k:p] (k+1)ème et pème éléments (le premier élément à l’indice 0)
L[:k] du début jusqu’au kème
L[-1] dernier élément
L[:-1] L amputée du dernier élément
L[:len(L)-1] Idem : L amputée du dernier élément
L[0] premier élément
L[i]=val remplace L[i] par val (si L[i] existe, sinon exception IndexError).
L=list(itérable) crée une liste à partir d’un itérable (comme range()), une liste est elle-même itérable.
len(L) nombre d’éléments de L
L.append(val) ajout d’un élément (à la fin, L est modifiée)
L.remove(val) suppression de la première occurrence de val (L est modifiée)
L.reverse() renverse L (L est modifiée)
L.index(val) renvoie l’indice de la 1ère occurrence de val dans L, erreur si val pas dans L.
L.copy() copie le contenu de L
L.count(val) compte le nombre d’occurrence de val dans L
L.extend(itérable) ajoute à L les éléments donnés par itérable, équivalent à L[len(L):] = liste ...
del(L[i]) ou del D[i] effacement de l’élément d’indice i d’une liste (L est modifiée)
L.clear() efface le contenu de L. Équivalent à del L[:]
L.insert(i, x) insertion de x avant l’indexe i
L.insert(0, x) insère x au début de L et L.insert(len(L), x) est équivalent à L.append(x).
L.pop() supprime et renvoie le dernier élément.
L.pop(i) supprime l’élément en position i et renvoie cet élément (i=-1 ’ le dernier)
• Plus généralement : du k_ème au p_ème élément s’écrira L[k-1:p] (le premier à l’indice 0)
Si L=[0,1,2,3,4,5,6,7,8,9], pour avoir du 3ème au 5ème, on écrit L[2:5]
+ pour L[0:10] ! [0,1,2,3,4,5,6,7,8,9], les indices d’une tranche (slice) peuvent être négatifs
x[-5:-2] ! [5,6,7]
x[-1] ! 9
+ Si l’intervalle est limité par un bord, on peut l’omettre : pour L[0:10] ! [0,1,2,3,4,5,6,7,8,9]
L[:] ! [0,1,2,3,4,5,6,7,8,9]
L[::2] ! [0,2,4,6,8]
L[-5:] ! [5,6,7,8,9]
L[8::-2] ! [8,6,4,2,0]
• Exemple d’affectation par tranches
L = [ 1, 2, 3, 4, 5]
L [ 2:3 ] = [ 0 , 0 ] # p l a c e ’ 0 ’ à l ’ i n d i c e 2 e t a j o u t e t o u t l e r e s t e à l a s u i t e de c e l u i ci .
L
# [ 1, 2, 0, 0, 4, 5]
L [ 1:1 ] = [ 8 , 9 ] # Idem
L
# [ 1, 8, 9, 2, 0, 0, 4, 5]
• Copie de liste :
L= [ 1 ,2 ,3 ]
L1=L #L1 e s t homonyme de L ; ce n ’ e s t pas une c o p i e ( l a l i s t e a maintenant deux noms ! )
L [ 0 ] =6
L
# [ 6, 2, 3]
L1
# [ 6, 2, 3]
#Pour c o p i e r une l i s t e , i l f a u t ê t r e p l u s e x p l i c i t e :
L2=L [ : ] # c o p i e r v r a i e m e n t L dans L2
L [ 1 ] =7
L
# [ 6 ,7 , 3 ]
L1
# [ 6 ,7 , 3 ]
L2
# [ 6 ,2 , 3 ]
+ On dit qu’en Python, une variable est avant tout son contenu et le nom n’est qu’un attribut de la variable. C’est
pour cette raison qu’on doit copier le contenu. Cette différence reflète le comportement des copie-constructeurs.
Les listes #16
Ÿ N’oublions pas que ce comportement (deux noms font référence au même objet) s’applique aux objets mutables
(List, Dict, Set, etc.) 2 , pas aux non mutables (comme les entiers, constantes strings , tuples, None).
Pour éviter cette confusion, les fonctions de la librairie std de Python rendent None lorsqu’elles modifient un objet
mutable (cf, append, sort). Notons aussi que cette confusion n’arrive pas en cas de création d’un nouvel objet tel que
y=y+[10] (où y : un entier) ou sorted(liste).
Il y a une exception à cette règle : l’opérateur +=. Dans liste += [1,2,3], on applique en fait la fonction
liste.extend([1,2,3]) à l’objet mutable liste tandis que entier_y +=1 ou tuple1 += (1,2,3) créent de
nouvelles variables car les entiers et les tuples ne sont pas mutables.
Enfin, pour savoir si deux variables font référence à un même objet , utiliser is ou la fonction id().
a = [ 5, 2, 3, 1, 4]
a . s o r t ( ) # T r i s u r p l a c e ( l a l i s t e e s t m o d i f i ée )
a
# [ 1, 2, 3, 4, 5]
s o r t e d ( { 1 : ’D ’ , 2 : ’B ’ , 3 : ’B ’ , 4 : ’E ’ , 5 : ’A ’ } )
# [ 1, 2, 3, 4, 5]
+ Remarques : sort() ne s’applique qu’aux listes alors que sorted() s’applique à tout ce qui "itérable" (y
compris les Dicos).
• sorted() et sort() acceptent un paramètre key qu’on peut utiliser pour préparer chaque élément avant le
tri.
#Dans c e t exemple , on demande ( par s p l i t ( ) ) à i s o l e r l e s mots p u i s à t r i e r l e u r frome minuscule
s o r t e d ( " Ceci e s t une Chaine de c a r a c t è r s Debase ! " . s p l i t ( ) , key= s t r . l o w e r ) ) # passer d ’ abord en minuscules
# [ ’ c a r a c t è r s ’ , ’ Ceci ’ , ’ Chaine ’ , ’ de ’ , ’ Debase ! ’ , ’ e s t ’ , ’ une ’ ]
+ Remarques : la liste student_tuples contient des tuples (ici des triplets). Voir plus loin pour les tuples la section
XIII page 20.
Ici, on peut aussi utiliser sort().
• Par exemple :
S= [ 1 , 2 , 3 , 4 ]
f o r x i n reversed (S) :
print (x)
"""
4
3
2
1
"""
• Ou par :
S= [ 1 , 2 , 3 , 4 ]
f o r x i n S [ :: 1] :
print (x)
"""
4
2. Pour faire court, un objet mutable est celui dont la valeur peut changer. Par opposition aux objets non-mutables. Cette propriété découle
du type de l’objet en question.
Les listes #17
3
2
1
"""
"""
0 a
1 b
2 c
3 d
4 e """
• On peut réaliser le même effet avec un accès aux éléments par indice :
S = [ ’a ’ , ’b ’ , ’c ’ , ’d ’ , ’e ’ ]
f o r i n d e x i n range ( l e n ( S ) ) :
p r i n t ( index , S[ index ] )
"""
0 a
1 b
2 c
3 d
4 e """
Préconditions :
ici, on précise les conditions d’applications des fonctions partielles
Par exemple : depile(p) : not(est_vide(p)) ....
d e f empile ( p , a ) :
p . append ( a )
def d e p i l e ( p ) :
try :
p . pop ( )
return p
except :
p r i n t ( " La p i l e e s t v i d e ! " )
r e t u r n None
def top ( p ) :
try :
return p[0]
except :
p r i n t ( " La p i l e e s t v i d e ! " )
r e t u r n None
d e f e s t _ v i d e ( p ) : r e t u r n p== [ ]
# Tests
p r i n t ( " P il e i n i t i a l e " . center (50 , ’ ’ ) )
l i f o = i n i t (5 , 8 , 9)
print ( " lifo : " , lifo )
i n p u t ( ’ E n t r ée pour c o n t i n u e r . . . ’ )
p r i n t ( " Empilage " . c e n t e r ( 5 0 , ’ ’ ) )
empile ( l i f o , 11)
print ( " lifo : " , lifo )
i n p u t ( ’ E n t r ée pour c o n t i n u e r . . . ’ )
p r i n t ( " Depilages " . c e n t e r ( 5 0 , ’ ’ ) )
f o r i i n range ( 5 ) :
depile ( l i f o )
print ( " lifo : " , lifo )
• Traces :
3) Les éléments manquants étant estimés, calculer µi+1 ; poser les éléments manquants de départ =µi ; i = i + 1 et aller à 2)
4) Stopper les itérations si µk+1 ' µk
M5=M # Synonymie
# Copions autrement
M3=M[ : ]
M3
# [ [ 1, 2, 3] , [ 4, 5, 6] , [ 7, 8, 9] ]
# On m o d i f i e M3
M3[ 1 ] [ 1 ] =10
M
# [ [ 1 , 2 , 3 ] , [ 4 , 10 , 6 ] , [ 7 , 8 , 9 ] ] # M e s t également m o d i f i ée
# La bonne f a çon :
i m p o r t copy
M4=copy . deepcopy (M)
M4
# [ [ 1 , 2 , 3 ] , [ 4 , 10 , 6 ] , [ 7 , 8 , 9 ] ]
# On m o d i f i e M
M[ 2 ] [ 2 ] =20
M
# [ [ 1 , 2 , 3 ] , [ 4 , 10 , 6 ] , [ 7 , 8 , 20 ] ] # M a b i e n changé
M4
# [ [ 1 , 2 , 3 ] , [ 4 , 10 , 6 ] , [ 7 , 8 , 9 ] ] # Mais pas M4
XIII Tuples
• Le tuple vide se note : ()
• On accède au range d’un élément d’un tuple par la fonction index.
• On teste l’appartenance d’un élément à un tuple par in.
• Si les (éléments des) tuples sont des objets non mutables, on ne peut pas les modifier.
• Exemple :
a_tuple = (1 , 2)
a _ t u p l e += ( 3 , 4 )
a_tuple
# (1 , 2 , 3 , 4)
# a _ t u p l e [ 0 ] += 3 : e r r e u r : a f f e c t a t i o n / m o d i f i c a t i o n i n t e r d i t e s
a_tuple [ 3 ]
# 4
• Mais si un élément du tuple est mutable (ici une liste), alors les modifications sont possibles :
a _ t u p l e += ( [ ’ H e l l o ’ ] , ’ P a r i s ’ )
a_tuple
# (1 , 2 , 3 , 4 , [ ’ Hello ’ ] , ’ Paris ’ )
• Modifions la liste dans le tuple d’une autre manière (devrait être autorisée) :
+ Préférez utiliser "append" (ici utilisé en l’état), voir aussi l’ajout de ’Good Luck’ (ci-dessous) :
a _ t u p l e [ 4 ] . append ( ’ I n ’ )
a_tuple
# ( 1 , 2 , 3 , 4 , [ ’ H e l l o ’ , ’ World ’ , ’ o f L i o n s ’ , ’ I n ’ ] , ’ P a r i s ’ )
• On peut ajouter des doublets ou plus à un tuple. On va ajouter un couple puis un triplet :
a _ t u p l e += ( 5 , ’ t o t o ’ )
a_tuple
# ( 1 , 2 , 3 , 4 , [ ’ Good Luck ’ , ’ World ’ , ’ o f L i o n s ’ , ’ I n ’ ] , ’ P a r i s ’ , 5 , ’ t o t o ’ )
a _ t u p l e += ( 1 0 , 2 0 , 3 0 )
a_tuple
# ( 1 , 2 , 3 , 4 , [ ’ Good Luck ’ , ’ World ’ , ’ o f L i o n s ’ , ’ I n ’ ] , ’ P a r i s ’ , 5 , ’ t o t o ’ , 10 , 20 , 30)
t [0]
# ’a ’
t [ 1]
# ’ example ’
t [ 1:3 ]
# ( ’b ’ , ’c ’)
z in t
# True
y
# ’b ’
z
# ’e ’
sanculottides
# 6
• Mais aussi, il est possible d’associer un range 6= 0 au premier élément. Noter la fonction len :
l e n ( ( v e r t u , genie , t r a v a i l , o p i n i o n , recompenses , r e v o l u t i o n , s a n c u l o t t i d e s ) )
#7
% a_tuple
% # ( 1 , 2 , 3 , 4 , [ ’ God Luck ’ , ’ World ’ , ’ o f L i o n s ’ ] , ’ P a r i s ’ , 10 , 20 , 30)
%
% p r i n t ( * a_tuple )
% # 1 2 3 4 [ ’ God Luck ’ , ’ World ’ , ’ o f L i o n s ’ ] P a r i s 10 20 30
%
+ print renvoie None (au cas où vous vous laisseriez aller à la programmation fonctionnelle !).
print ( print (1) )
# 1
# None
’ (%d ) ’ % x
# Donne > ’(5) ’
’ Je connais un mouton à %d p a t t e s . ’ % x
# Donne > ’ Je connais un mouton à 5 p a t t e s . ’
y=2
’ Je connais %d moutons à %d p a t t e s . ’ % ( y , x )
# Donne > ’ Je connais 2 moutons à 5 p a t t e s . ’
+ Remarques : dans ces exemples, "%" sépare le string exprimant le format (e.g. "%d") de la valeur à écrire
(e.g. "x").
• On peut maitriser les longueurs des champs (e.g. pour justifier des colonnes) :
Ÿ La syntaxe à suivre est %[flag][longueur][.precision] variable
r =2
p r i n t ( " La s u r f a c e pour un rayon <%3d> sera <%8.3 f > " % ( r , r * r * p i ) )
# Donne > La s u r f a c e pour un rayon < 2> sera < 12.566 >
Ici, %3d demande à écrire r sur 3 positions (on écrit entre <> pour plus de clarté). Pour la surface, %8.3f demande
une longueur totale de 8 places (le ’.’ compris) dont 3 chiffres après la virgule. En cas d’erreur de notre part pour la
totalité de la longueur, par exemple si on demande <%1.3f>, Python outrepasse l’erreur et utilise ce qui est juste (ici
3 chiffres après la virgule), sinon le minimum de longueur requise.
Par exemple, si on demande %4.2f pour la surface, les 2 chiffres après la virgule demandés plus une place nécessaire
pour le ’.’ feront que le total de 4 places ne suffiront pas (il faut au moins 2 places pour 12). Au final, on écrira
<12.57>.
Noter que %3d est équivalent à %3i.
Quelques informations supplémentaires (extrait de la doc) :
Introduction à la mise en page #23
Quelques exemples :
p r i n t ( " %10.3e "% ( 35 6 . 0 8 97 7 ) )
#Donne > 3.561 e+02
p r i n t ( " %10.3E"% ( 35 6 . 0 8 97 7 ) )
#Donne > 3.561E+02
p r i n t ( "%10o "% ( 2 5 ) )
#Donne > 31
p r i n t ( " %10.3o "% ( 2 5 ) )
#Donne > 031
p r i n t ( " %10.5o "% ( 2 5 ) )
#Donne > 00031
p r i n t ( "%5x "% ( 4 7 ) )
#Donne > 2f
p r i n t ( " %5.4x "% ( 4 7 ) )
#Donne > 002 f
p r i n t ( " %5.4X"% ( 4 7 ) )
#Donne > 002F
p r i n t ( " Only one percentage s i g n : %% " % ( ) )
#Donne > Only one percentage s i g n : %
p r i n t ( ’%d ’ % 0x12 )
#Donne > 18
• D’autres exemples :
" F i r s t argument : { 0 } , second one : { 1 } " . f o r m a t ( 4 7 , 1 1 )
# Donne >’ F i r s t argument : 47 , second one : 11 ’
" Second argument : { 1 } , f i r s t one : { 0 } " . f o r m a t ( 4 7 , 1 1 )
# Donne >’Second argument : 11 , f i r s t one : 47 ’
" Second argument : { 1 : 3 d } , f i r s t one : { 0 : 7 . 2 f } " . f o r m a t ( 4 7 . 4 2 , 1 1 )
# Donne >’Second argument : 11 , f i r s t one : 47.42 ’
" F i r s t argument : { } , second one : { } " . f o r m a t ( 4 7 , 1 1 )
# Donne >’ F i r s t argument : 47 , second one : 11 ’
# arguments can be used more than once :
...
" various precions : { 0:6.2 f } or { 0:6.3 f } " . format (1.4148)
# Donne >’ v a r i o u s p r e c i o n s : 1.41 o r 1 . 4 1 5 ’
• Aussi, on peut remplacer la numérotation des colonnes et renommer les argument. Dans l’exemple ci-dessous, le
rayon représente r et la surface la superficie.
r =2
" La s u r f a c e pour un rayon { rayon : 3 d } sera { s u r f a c e : 8 . 3 f } " . f o r m a t ( s u r f a c e = r * r * p i , rayon= r )
# Donne > ’ La s u r f a c e pour un rayon 2 sera 12.566 ’
• D’autres exemples (noter les longueurs des champs utilisées pour les strings).
• N.B. : le symbole ’<’ impose une justification à gauche (avec ajoute d’espaces si nécessaires) et ’>’ une justification
à droite.
p r i n t ( ’ %(language ) s has %(number ) 03d quote t y p e s . ’ % { " language " : " Python " , " number " : 2 } )
# Python has 002 quote t y p e s .
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
# On peut a u s s i ne r i e n é c r i r e e n t r e l e s { } :
x , y= ’ choux ’ ,1
p r i n t ( " I l n ’ y a que { } f a çon de p l a n t e r des { } chez { } " . f o r m a t ( y , x , ’ nous ’ ) )
# Donne > I l n ’ y a que 1 f a çon de p l a n t e r des choux chez nous .
En fahrenheit : 0 En c e l s i u s : 17.77777777777778
En fahrenheit : 20 En c e l s i u s : 6.666666666666667
En fahrenheit : 40 En c e l s i u s : 4.444444444444445
En fahrenheit : 60 En c e l s i u s : 15.555555555555557
En fahrenheit : 80 En c e l s i u s : 26.666666666666668
En fahrenheit : 100 En c e l s i u s : 37.77777777777778
"""
""" TRACE
En fahrenheit : 0 En celsius : 17.778
En fahrenheit : 20 En celsius : 6.667
En fahrenheit : 40 En celsius : 4.444
En fahrenheit : 60 En celsius : 15.556
En fahrenheit : 80 En celsius : 26.667
En fahrenheit : 100 En celsius : 37.778
"""
"""
Fahrenheit celsius
0 17.8
20 6.7
40 4.4
60 15.6
80 26.7
100 37.8
"""
Ÿ Noter que dans for i in range(5) : ..., la valeur de i à la sortie de ce for est 4 (et non 5 comme on
pourrait le penser).
Itérations : While, for #27
Noter que intervalle est évalué une seule fois et donne lieu à un itérateur dont les valeurs sont assignées une
par une à iteration_for (donc, c doit pouvoir recevoir une valeur, ou être une lvalue, ce qui exclue par exemple
un appel de fonction).
for peut provoquer une exception "StopIteration".
else_expression est exécutée à la fin des itérations ou suite à l’exception "StopIteration".
corps_for peut contenir break.
Si break est exécuté, on abandonne l’itération sans exécuter else_expression.
corps_for peut contenir continue. S’il est exécuté, on passe à l’itération suivante (mais s’il n’y aucune autre
itération possible, else_expression sera exécutée avant de terminer).
Les variables de iteration_for reçoivent des valeurs qui écrasent leur éventuelle ancienne valeur :
# Observer i
i =12
f o r i i n range ( 5 ) :
p r i n t ( i , end= ’ ’ )
i =42
print ( i )
# Donne > : 0 1 2 3 4 42
• On constate que i=12 ni les i=42 n’ont aucun effet sur i de iteration_for. Cependant, la valeur finale de i=42
(fait à la toute dernière itération).
i =12
f o r i i n range ( 5 ) :
p r i n t ( i , end= ’ ’ )
e l s e : i =42
print ( i )
# Donne > : 0 1 2 3 4 42
Les variables de iteration_for existeront après les itérations. Elles auront leur valeur finale de la dernière
itération.
Éviter de modifier intervalle dans corps_for sous peine de surprises.
+ Le schéma while dispose également d’une clause else : ... dont le comportement est identique à celle
présente dans for. Idem pour continue et break dans le schéma while.
• Écrire et tester ces fonctions, par exemple avec les valeurs somDiv(12), estParfait(6), estPremier(31) et
estChanceux(11).
n b _ c h i f f r e s = n b _ l e t t r e s =0
f o r c a r i n ph :
i f c a r == ’ . ’ :
break
i f car . isalpha ( ) :
n b _ l e t t r e s +=1
i f car . i s d i g i t ( ) :
n b _ c h i f f r e s +=1
+ Dans le version ci-dessus, la présence de ’.’ n’est pas contrôlée lors de la lecture de la phrase. Même si on teste
cette présence dans le code !
• Dans la version suivante, on va s’assurer de la lecture du ’.’ final tout en lisant la phrase sur plusieurs lignes.
stock= ’ ’
w h i l e True : # l i r e j u s q u ’ au ’ . ’
ph= i n p u t ( " Donner une ( s u i t e de ) phrase t e r m i n ée par un p o i n t " )
s t o c k +=ph # stock contiendra toutes les lignes
i f ph [ 1] == ’ . ’ :
break
n b _ c h i f f r e s = n b _ l e t t r e s =0
f o r car i n stock :
i f c a r == ’ . ’ :
break
i f car . isalpha ( ) :
n b _ l e t t r e s +=1
i f car . i s d i g i t ( ) :
n b _ c h i f f r e s +=1
p r i n t ( " Dans l a phrase %s , i l y a %d l e t t r e s e t %d c h i f f r e s " % ( stock , n b _ l e t t r e s , n b _ c h i f f r e s ) )
• Pour compter la somme de toutes les voyelles dans un string ch2 (converti à la volée en minuscule) :
ch2 = " L ’ un a d i t : puisque l e s gens ne f o n t pas a t t e n t i o n à l e u r s biens , j e me s u i s s e r v i en s o r t a n t ! "
v o y e l l e s = " aeiou " ; t o t a l _ v o y e l l e s =0 # On ne prend que l e s v o y e l l e s minuscules
for v in voyelles : # On compte l e nombre d ’ occurrence de chaque v o y e l l e dans
t o t a l _ v o y e l l e s += ch2 . l o w e r ( ) . count ( v ) # ch2
# 29
+ Remarques :
Noter iMin = t.index(min(t[i:])) : on veut l’indice du minimum de la liste t à partir du ième élément.
XVI-1 Exemple 1
• Pour l’exercice pair-impair, on peut contrôler la lecture d’un entier au clavier.
a= i n p u t ( " Donner l e c o e f f i c i e n t a : " )
try :
a= i n t ( a )
i f ( a%2 ==1) :
p r i n t (a , " est impair " )
else :
p r i n t (a , " est pair " )
except V a l u e E r r o r : # On v i e n t i c i s i a= i n t ( a ) provoque une e x c e p t i o n .
p r i n t ( " pas un nbr " )
Si la valeur rentrée au clavier n’est pas un entier, la conversion a=int(a) provoque une exception prédéfinie. De
ce fait, la ligne suivante cette erreur n’est pas exécutée et Python cherche une clause except ValueError : qui va
de paire avec try et exécute ce qui y est prévu.
# I c i , on e s t s u r que a c o n t i e n t un e n t i e r
+ Remarques : ici, l’exception prend un nom locale (e) pour être traitée / détaillé.
• Dans cet exemple, l’exception e contient la chaîne "invalid literal for int() with base 10:
’a’", l’expression e.args[0].split(": ") sépare cette chaîne de part et d’autre de ": " et donne une
liste à 2 éléments contenant les deux chaînes [’invalid literal for int() with base 10’, ’a’]
et finalement l’indice [1] représente ’a’ (le 2e élément).
• Cependant, sous spyder, on peut demander l’exécution dans le menu Exécution/Configurer une fenêtre "terminal" :
Sous spyder, on peut associer à chaque fichier Python son type de console d’exécution (dans le menu Exécution/-
Configurer, choisir OK au lieu d’exécuter immédiatement). A partir de ce moment, l’exécution de ce code (placé
dans un fichier .py) aura lieu sous la console précisée.
+ Noter que si la fenêtre ferme immédiatement, c’est qu’il y a une erreur dans le code ! Il faut d’abord la corriger !
min=max=0
v a l = i n p u t ( " donner l e p r e m i e r e n t i e r " )
try :
val= i n t ( val )
min=max= v a l
# I c i , on a l u un e n t i e r e t i n i t i a l i s é min e t max
w h i l e True :
try :
v a l = i n p u t ( " donner un e n t i e r " )
val= i n t ( val )
i f ( v a l < min ) :
min= v a l
i f v a l > max :
max= v a l
+ Rappel : pour pouvoir terminer les lectures avec ctrl-D (ctrl-Z), exécutez ce code dans une fenêtre
"terminal". Sous votre IDE, cela ne marchera pas.
w h i l e True :
try :
v a l = i n t ( i n p u t ( " donner l e p r e m i e r e n t i e r " ) )
min=max= v a l
break
except V a l u e E r r o r : #On v i e n t i c i s i on n ’ a pas donné un e n t i e r
continue
# I c i , on a l u un e n t i e r e t i n i t i a l i s é min e t max
w h i l e True :
try :
v a l = i n t ( i n p u t ( " donner un e n t i e r " ) )
i f ( v a l < min ) : min= v a l
i f v a l > max : max= v a l
Exemple 2 : Supposons que l’on veuille trouver le plus grand réel (à 1% près) de Python. L’exemple suivant multiplie
un nombre (initialisé à 1000000) par un facteur de 1,01 jusqu’à ce que cette multiplication ne soit plus possible faute
de capacité ! Dans ce dernier cas, le nombre devient infini (inf de Python) et on lève, par raise, une exception
prédéfinie ValueError dont le traitement affiche la plus grande valeur de facteur atteinte avant de devenir inf
= float(’inf’).
f a c t e u r = 1000000
w h i l e True :
try :
i f 1/ facteur :
save = f a c t e u r
f a c t e u r * = 1.01 # l’opération qui provoquera une exception
p r i n t ( ’ nombre grand a c t u e l : ’ , save )
else :
raise ValueError # on lève une exception prédéfinie
except V a l u e E r r o r :
p r i n t ( ’ l i m i t e : ’ , save )
break
Passer à l a s u i t e ....
except :
pass
d e f f o n c t i o n _ a _ e c r i r e ( params ) :
pass # La f o n c t i o n e x i s t e . Pensez à l a complé t e r .
• pass est également utilisé pour créer des classes vides qui doivent exister ! Voir Inf-TC2. On l’utilise aussi dans les
exceptions si on veut les ignorer.
Génération de nombres aléatoires #33
random . c h o i c e ( ’ a b c d e f g h i j ’ ) # Choix a l é a t o i r e
#Donne > ’c ’
items = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 ]
random . s h u f f l e ( i t e m s )
items
#Donne > [ 7, 3, 2, 5, 6, 4, 1]
# fonctions
def l i s t A l e a t o i r e I n t ( n , a , b ) :
" " " Retourne une l i s t e de <n> e n t i e r s a l e a t o i r e s dans [ <a> . . <b> ] . " " "
r e t u r n [ r a n d i n t ( a , b ) f o r i i n range ( n ) ]
# programme p r i n c i p a l
seed ( ) # i n i t i a l i s e l e g e n e r a t e u r de nombres a l e a t o i r e s
t = l i s t A l e a t o i r e I n t ( 1 0 0 , 2 , 125) # c o n s t r u c t i o n de l a l i s t e
## c a l c u l de l ’ i n d i c e du minimum de l a l i s t e
i M i n = t . i n d e x ( min ( t ) )
## A f f i c h a g e s
p r i n t ( " { } t [ iMin ] = { } " . format ( " Indice : " , t [ iMin ] ) ) # V o i r p l u s l o i n pour l a f o n c t i o n f o r m a t
+ Remarques :
Noter les deux {} : la première est pour "Indice : " et la seconde pour t[iMin].
Ÿ voir section XIV page 22
# fonctions
def l i s t A l e a t o i r e F l o a t ( n ) :
" " " Retourne une l i s t e de <n> f l o t t a n t s a l e a t o i r e s . " " "
r e t u r n [ random ( ) f o r i i n range ( n ) ]
# programme p r i n c i p a l
n = i n t ( i n p u t ( " E n t r e z un e n t i e r [ 2 . . 100 ] : " ) )
w h i l e n o t ( 2 <= n <= 100) : # s a i s i e f i l t r e e
n = i n t ( i n p u t ( " E n t r e z un e n t i e r [ 2 . . 100 ] , s . v . p . : " ) )
seed ( ) # i n i t i a l i s e l e g e n e r a t e u r de nombres a l e a t o i r e s
t = l i s t A l e a t o i r e F l o a t ( n ) # c o n s t r u c t i o n de l a l i s t e
Génération de nombres aléatoires #34
+ Donc :
⇤ randn(d1 , ..., dn ) + µ est équivalent à normal(µ, , d1 , ..., dn ) di : taille de la ième dimension
• A noter ( random ) :
import random
random.randint(a, b) : Échantillonnage Uniforme : renvoie un entier a N b
random.random() renvoie un réel dans [0 .. 1[.
random.gauss(µ, ) renvoie un réel de N (µ, )
random.choice(seq) renvoie un élément aléatoire de la séquence seq
random.randrange[début], fin, [pas]) équivalent à choice(range([début], fin, [pas])).
P. Ex. : random.randrange(0, 101, 2) renvoie un entier pair dans 0..100
random.shuffle(seq[, random]) "mélange" la séquence X sur place et seq devient égale à l’une
de ses propres permutations.
Le 2e argument est par défaut la fonction random() qui renvoie un réel N dans [0 .. 1[.
Si le 2e argument est présent, il doit être le nom d’une fonction sans argument.
Par exemple, si on définit
def f() : return 0 et L=[7, 2, 10, 7, 7, 18, 7, 7, 15, 11], alors
random.shuffle(L,f) place dans L la permutation [2, 10, 7, 7, 18, 7, 7, 15, 11, 7].
Puis à la répétition de ce même appel, le 1er élément de L est placé à la fin le le 2e devient le premier, ...
random.sample(seq, k) renvoie une liste de taille k des éléments sans remise de seq.
def tirage_uniforme_k_of_n_avec_remise ( n , k ) :
if k > n :
r a i s e V a l u e E r r o r ( " k (%d ) d o i t ê t r e =< que n (%d ) " % ( k , n ) )
T= [ x f o r x i n range ( 1 , n +1 ,1) ] # On c o n s t i t u e une urne avec p o b j e t s
f o r i i n range ( k ) : # T i r a g e de k numé r o s
d= r a n d i n t ( 1 , n )
# On permute l e d ème é l ément de l ’ urne e t l a d e r n i e r e
temp=T [ d 1]
T [ d 1] =T [ n 1]
T [ n 1] =temp
n=n 1
r e t u r n T [ n : n+k+1 ]
n= i n t ( i n p u t ( " La v a l e u r de n ? " ) )
k= i n t ( i n p u t ( " La v a l e u r de k ( parmi n ) ? " ) )
try :
p r i n t ( " Le t i r a g e : " , t i r a g e _ u n i f o r m e _ k _ o f _ n _ a v e c _ r e m i s e ( n , k ) )
except V a l u e E r r o r as e r r :
p r i n t ( " Error : { 0 } " . format ( e r r ) )
def tirage_gauss_centre_reduit ( ) :
x= u n i f o r m ( 0 , 1 )
y= s q r t ( 2 * l o g ( u n i f o r m ( 0 , 1 ) ) )
y = y * cos ( x * 2 * p i )
return y
try :
n= i n t ( i n p u t ( " combien de v a l e u r s : " ) )
f o r i i n range ( n ) :
p r i n t ( " Le t i r a g e : " , t i r a g e _ g a u s s _ c e n t r e _ r e d u i t ( ) )
except V a l u e E r r o r as e r r :
p r i n t ( " Error : { 0 } " . format ( e r r ) )
+ Il faudra un tirage d’un grand nombre de valeurs pour que la moyenne et l’écart type correspondent !
Ÿ Pour nos 5 valeurs, les choses sont mal engagées ! Vérifions :
np . mean ( s )
# 0.40500364849867287
np . s t d ( s , ddof =1)
# 0.80987532417316277
Génération de nombres aléatoires #36
from random i m p o r t *
somme=0
f o r n i n range ( 1 0 0 0 ) :
i f c h o i c e ( t o u t e s _ c a r t e s ) == " 1 pique " :
somme+=1
# > 0.002
# 0.019230769230769232
Ÿ Voir la section XXIV page 52 pour plus de détails sur les listes en compréhension.
• Exemples :
my_name
# ’ David ’
my_name . upper ( )
# ’ DAVID ’
my_name . c e n t e r ( 1 0 )
# ’ David ’
my_name . f i n d ( ’ v ’ )
# 2
my_name . s p l i t ( ’ v ’ )
# [ ’ Da ’ , ’ i d ’ ]
+ Remarque : comme pour les listes, les tuples, on peut multiplier un string par un entier n pour répéter son contenu
n fois :
my_name
# ’ David ’
my_name * 3
# ’ DavidDavidDavid ’
+ Rappel : Par contre, parmi les listes, tuples et constantes strings, seules les listes sont mutables (on peut modifier
la valeur d’un de ses éléments).
Imbrication de fonctions #38
# main ( )
f1 (2) # donne 1
g1 ( 2 ) # donne une e r r e u r : g1 ( ) e s t incnnue
• Remarquez que la fonction g1() n’est visible qu’à l’intérieur de la définition de la fonctions f1(). On ne peut donc
pas l’appeler à partir du niveau 0.
• Noter que dans def g1(x) : , le paramètre formel x devient une variable locale à g1(.) ; elle reçoit sa valeur initiale
(1) par copie et n’aura plus de lien avec x de f1(). Voir section XX, page 42 sur la portée des variables.
x=12
fonc ( x ) ; x
#12 > x n ’ a pas changé de v a l e u r
Les variables du main (niveau global) sont accessibles dans une fonction via le mot clé global. Si elles existent
au préalable et au niveau global, elles sont ainsi référencées. Si elles n’existent pas, elles sont créées au niveau
global. On peut ainsi créer une variable (globale) pour le compte du niveau global dans une fonction.
d e f machin ( ) :
global bidule
b i d u l e = 50
machin ( ) ; b i d u l e
# 50
Ÿ Il y eu donc une création. Par contre, s’il s’agit d’une modification, ça ne passera pas :
def t r u c ( ) :
g l o b a l muche
muche += 50
truc ()
# NameError : name ’ muche ’ i s n o t d e f i n e d
Ÿ Cette fois, on a essayé de modifier muche. Dans ce cas, muche doit avoir existé avant l’appel de truc()
puisqu’on ajoute 50 à son ancienne valeur :
def t r u c ( ) :
g l o b a l muche
muche += 50
muche=10
t r u c ( ) ; muche
# 60
Supposons qu’une fonction définisse d’autres fonctions (par exemple, f() définit g() qui définit u()). Pour accéder
à la variable x de f(), les fonctions g() et u() utilisent le mot clé nonlocal x. La variable x doit exister dans f() et y
avoir déjà reçu une valeur. De même, pour accéder à la variable z de g(), u() utilisera nonlocal z.
Imbrication de fonctions #39
def f ( ) :
x = 1
def g ( ) :
nonlocal x
x+=10
p r i n t ( ’ x dans g ( ) : ’ , x )
def u ( ) :
nonlocal x
x+=100
p r i n t ( ’ x dans u ( ) : ’ , x )
# On e s t dans g ( )
u()
# On e s t dans f ( )
g()
x += 1000
p r i n t ( ’ x dans f ( ) : ’ , x )
f ()
# x dans g ( ) : 11
# x dans u ( ) : 111
# x dans f ( ) : 1111
Les 3 fonctions écriront global k pour utiliser une variable k du niveau 0 si k est définie avant l’appel de f().
Si k n’existe pas au niveau global avant cet appel, elle existera désormais (voir le premier exemple ci-dessous).
Le mot clé nonlocal exprime le besoin d’utiliser d’autres variables que les locales. Ce mot clés ne définit pas
de variable et ne change pas le statut d’une variable. Il fait seulement référence à une variable existante des
niveaux englobants.
Un paramètre formel d’une fonction est une variable locale à la fonction, il peut donc être référencé par nonlocal.
val_l = 0
f ()
val_l
val_g
# On o b t i e n t
# 0
# 400
Ÿ Il est important qu’ici, global val_g soit citée au moins 2 fois ! Faute de quoi on n’aura pas affaire
à une variable globale.
# main ( ) :
z = 3
k = 4
f (z ,k)
p r i n t ( ’ r e t o u r de f ( ) : z dans main ( ) : ’ , z, ’ k dans main ( ) : ’ , k)
Un dernière chose : sous Python, on a des paramètres nommés. Ce mécanisme permet une certaine souplesse
lors des appels dans la mesure où en nommant les arguments, on n’est pas obligé de respecter l’ordre des
paramètres formels donné dans la signature de la fonction.
Dans l’exemple suivant, remarquer l’ordre des arguments d’appel et celui des paramètres formels :
d e f f ( p e t i t , moyen , grand ) :
p r i n t ( p e t i t , ’ <= ’ , moyen , ’ <= ’ , grand )
# 5 <= 9 <= 12
• Cet enchaînement nous conduit à un état de base (d’induction) : on finira par arriver à l’état où pour trier une
tranche du tableau à 2 éléments T [n 1..n], il faudra trier T [n] (il est déjà trié car c’est un singleton). Donc, la première
élément à être inséré à sa placer sera T [n 1] à insérer dans T [n 1..n] par insere_a_sa_place(liste, val).
• Ainsi, T [n 1..n] devient trié et l’insertion suivante va insérer T [n 2] à sa place dans T [n 2..n].... et enfin, on
finira par insérer T [0] à sa place dans T [0..n].
• Un exemple : soit T = [5, 2, 3, 9, 1, 6]. On doit
! trier T = [2, 3, 9, 1, 6] (qui doit donner T [1, 2, 3, 6, 9]) puis y insérer 5 à sa place.
!trier T = [3, 9, 1, 6] (qui doit donner T [1, 3, 6, 9]) puis y insérer 2 à sa place.
! ....
! trier T = [6] (il l’est déjà) puis y insérer 1 à sa place.
insérer 1 dans T = [6] donne [1, 6]
...
insérer 2 dans T [1, 3, 6, 9] donne T [1, 2, 3, 6, 9]
insérer 5 dans T [1, 2, 3, 6, 9] donne T [1, 2, 3, 5, 6, 9]
• Écrire la méthode de Tri par insertion. Utiliser une fonction imbriquée pour l’insertion des éléments à leur place
dans la partie triée. Quelle est la complexité de cette méthode de tri ?
Imbrication de fonctions #41
• Exemple : L = [4, 5, 2, 3, 1, 9, 6, 0, 7], la fonction my_split donne (split correspond à une fonction prédéfinie de
Python) :
L1 : 4,5 puis 1,9 puis 0,7 ! L1 = [4, 5, 1, 9, 0, 7]
L2 : 2,3 puis 6 , ! L2 = [2, 3, 6]
• Ensuite, on fusionne L1 et L2 (un peu comme merge-sort en mettant toujours le plus petit élément d’abord) :
La fusion donne : L : 2,3 (de L2 car 2 et 3 sont plus petits que 4) puis 4,5,1 (de L1 car ils sont plus petits que
6),6,9,0,7. Donc, le résultat de cette fusion est L = [2, 3, 4, 5, 1, 6, 9, 0, 7].
• Mais la liste L résultante de cette fusion n’est pas encore triée. On recommence avec my_split sur L :
L1 : [2,3,4,5 puis 0,7]
L2 : [1,6,9]
Ÿ On fusionne : L = [1, 2, 3, 4, 5, 0, 6, 7, 9]
• On re scinde L :
L1 : [1,2,3,4,5]
L2 : [0,6,7,9]
Ÿ On re fusionne : L = [0, 1, 2, 3, 4, 5, 6, 7, 9]
• La condition d’arrêt de cet algorithme est que la liste L2 renvoyée par my_split soit vide.
Complément sur la Visibilité des variables #42
x=15
fonc ( x )
print (x)
# Donne
16 # é c r i t par f o n c
15 # au r e t o u r de fonc , x n ’ a pas changé de v a l e u r
f ()
# Donne 1
+ Par contre :
a=1
def f ( ) :
a += 1
f ()
# Erreur
Ÿ Dans cet exemple, a += 1 provoque une erreur d’accès à a : la variable locale a référencée avant de recevoir
une valeur. Ce qui veut dire qu’il faut d’abord écrire a=.. et à partir de ce moment, les deux a seront différentes.
def g ( ) :
x=1
def f f ( ) :
x += 1
ff ()
g()
# Erreur
+ Règle : une fonction a accès en lecture aux variables définies dans son contexte ainsi que dans le contexte
englobant (cf : print(a) et print(x) ci-dessus).
Ÿ Si la variable accédée est non mutable (int, constante string, tuple, etc), toute modification de celle-ci
provoque une erreur.
Ÿ Par contre, pour une variable mutable (List, Dict, Set, etc.), la modification est possible.
Exemple :
L= [ ]
def f ( ) :
L . append ( 1 )
f ()
print (L)
# Donne [ 1 ]
Complément sur la Visibilité des variables #43
XX-2 global
• Un exemple :
d e f method ( ) :
# On change l e s t a t u t de " v a l u e " : e l l e sera g l o b a l e .
# Sans " g l o b a l " , l ’ a f f e c t a t i o n sera " l o c a l "
g l o b a l value
v a l u e = 100
value = 0
method ( )
value
# Donne 100
value = 0
method ( )
value
value1
# Donne
# 0
# 100
• Ici, global value1 (value1 n’existe pas encore) définit et affecte une valeur à value1.
+ Remarques : global var définit var si elle n’existe pas et la rend accessible à l’extérieur de toute fonction.
Si var existe déjà (à un niveau global), ce sera cette var qui sera référencée.
XX-3 nonlocal
• nonlocal a un comportement similaire à global mais pour des fonctions imbriquées. nonlocal veut dire ni global, ni
local. Une variable nonlocal fait référence à un niveau englobant.
d e f method ( ) :
d e f method2 ( ) :
# dans c e t t e f o n c t i o n i m b r i q u ée , ’ v a l u e ’ f a i t r e f e r e n c e à une v a r i a b l e ’ n o n l o c a l ’ .
nonlocal value
v a l u e = 100
# Set l o c a l .
v a l u e = 10
method2 ( )
# essai
method ( )
# Donne 100
• nonlocal rend pratique l’échange de variables entre les fonctions imbriquées. Sans nonlocal, on risque de provoquer
des conflits de noms entre un fonction imbriquée et le niveau englobant là où global ne rentre pas dans ce niveau de
détail.
• Il est communément admis que la plupart des fonctions Python n’ont besoin de ce mécanisme qui rend le code
Python obtenu plus complexe. Néanmoins, global et nonlocal peuvent convenir dans certains situations pour éviter
les conflits de noms.
Complément sur la Visibilité des variables #44
• Un exemple récapitulatif :
def scope_test ( ) :
def do_local ( ) :
spam = " l o c a l spam "
d e f d o _ n o nl o c a l ( ) :
n o n l o c a l spam
p r i n t ( " Dans d o_ n on l oc a l ( ) : " , spam )
spam = " n o n l o c a l spam "
def do_global ( ) :
g l o b a l spam # ( glob ) se superpose à l a dé f i n i t i o n ’ spam = " t e s t spam " ’
# p r i n t ( " Dans d o _ g l o b a l ( ) " , spam ) Provoquera une erreur : spam non défini.
spam = " g l o b a l spam " # ( glob ) le ’spam’ du niveau 0, pas celle de scope_test.
scope_test ( )
p r i n t ( " Dans l a p o r t ée g l o b a l ( hors l e s f o n c t i o n s ) : " , spam )
"""
• On note que :
do_local n’a pas changé la valeur de spam de scope_test. Ce que do_local a fait à spam n’est pas visible
à l’extérieur. Si on tente d’écrire spam au début de do_local, on provoque une erreur de définition.
Dans do_nonlocal, la référence à spam concerne spam de scope_test. L’affectation fait dans
do_nonlocal modifie donc spam de scope_test.
Dans do_global, on déclare global spam (une variable globale va exister !). Une tentative d’écriture (par
print) de ce spam provoque une erreur : la nouvelle occurrence de spam n’a pas encore de valeur ! Noter bien
qu’au retour de l’appel à do_global, spam vaut toujours nonlocal spam. Noter également que global
spam fera exister spam au niveau global (et affichée à la fin de la partie principale).
La fonction scope_test écrit ensuite la valeur de spam définie dans do_global.
+ Si on écrivait (sous Python) la valeur de spam, on obtiendrait global spam.
Complément sur la Visibilité des variables #45
d e f main ( ) :
g l o b a l v a r _g l o b 1
v a r _ g l o b 1 =1
p r i n t ( " v a r _ g l ob 1 avant appel de f ( ) " , v a r _ g l o b 1 )
f ()
p r i n t ( " v a r _ g l ob 1 apr ès l ’ appel de f ( ) " , v a r _ g l o b 1 )
def f ( ) :
g l o b a l v a r _g l o b 1
v a r _ g l o b 1 +=1
def g ( ) :
g l o b a l v a r _g l o b 2
v a r _ g l o b 2 +=10
# ZZ : l a f o n c t i o n p r i n c i p a l e __main__ DOIT e t r e en d e r n i e r !
# Tests f a i t . Plac ée avant g ( ) , e r r e u r de mé connaissance de g ( ) ! !
# mm s i on charge t o u t !
# Parce que dès que __main__ e s t r e n c o t r ée , e l l e e s t exé c u t ée !
l i s t e = [ 1 ,3 ,13 ,4 ,7 ,2 ,9 ,2 ,18 ]
print ( tri_bulle_iteratif ( liste ) )
# [ 1 , 2 , 2 , 3 , 4 , 7 , 9 , 13 , 18 ]
# programme p r i n c i p a l
seed ( ) # i n i t i a l i s e l e g e n e r a t e u r de nombres a l e a t o i r e s
N=10
t = [ r a n d i n t ( 2 , 125) f o r i i n range (N) ]
p r i n t ( " Avant l e t r i , l i s t e = { } " . f o r m a t ( t ) )
tri_bulle ( t ,0)
d e f my_cos ( x ) :
i f abs ( x ) < 1e 6 : c o s i n e =1
e l s e : c o s i n e = pow ( my_cos ( x / 2 ) , 2 ) pow ( my_sin ( x / 2 ) , 2 )
r e t u r n cosine
angle = math . p i / 3
p r i n t ( " avec n o t r e mé thode : { 0 : 8 . 6 f } " . f o r m a t ( my_sin ( angle ) +my_cos ( angle ) ) )
p r i n t ( " avec l a mé thode c l a s s i q u e : { 0 : 8 . 6 f } " . f o r m a t ( math . s i n ( angle ) +math . cos ( angle ) ) )
+ Remarques : il est important d’avoir à l’esprit que Python limite le nombre d’appels récursifs à une fonction
à 1000 fois. C’est une limitation de l’implantation du langage.
Par ailleurs, Python ne traite et ne supprime pas la récursivité terminale (pas encore !).
Un appel à gc pourrait éventuellement améliorer l’état de la mémoire.
Introduction à la récursivité #48
Méthode 1 - Pour calculer la médiane, il suffit de trier S puis de choisir l’élément du milieu.
€ Complexité : celle de l’algorithme de tri (au mieux O(N.Log(N))).
Méthode 2 - pour S de taille |S|, on peut trouver le kième plus petit élément (ici k = b |S|
2 c).
€ Le point fort de cette méthode est de ne trier que la plus petite sous séquence de S contenant le kième plus petit
élément. On étudiera cette méthode ci-dessous.
Méthode 3 - Construire un TAS (de complexité O(N), voir + loin) puis retirer k fois l’élément minimal (k= b|S|2c ).
€ Complexité : O(N.log2 N ) pour N 4
Pour trouver le kième plus petit élément de S, il suffit de repérer le sous tableau susceptible de contenir cet élément
et de traiter celui-ci. Par exemple : si k=8, on sait que le 8e plus petit élément de S ne peut être que dans Sd car la
somme |Sg| + |Sv| = 5 < 8. Ce qui permet d’écrire : selection(S,8) = selection(Sd,8-5) = selection(Sd,3).
N.B. : [Aho & al] montre qu’en moyenne, 2 divisions suffisent pour trouver la médiane. Voir [Aho & al] ou [Wirth]
pour 2 algorithmes de complexité O(n) pour obtenir le kième plus petit élément de S.
Déroulement d’un exemple : calcul de la médiane de S=< 2, 36, 5, 21, 8, 13, 11, 20, 5, 4, 1 > avec |S| = 11 et donc
k = 6.
selection(S,6) :
V1=2, Sg1=< 1 >, Sv1=< 2 > , Sd1=< 36, 5, 21, 8, 13, 11, 20, 5, 4 >
€ k > |Sg1| + |Sv1| ’ selection(Sd1, 6 - |Sg1| + |Sv1|) = selection(Sd1, 4)
selection(Sd1,4) : V2=36, Sg2=< 5, 21, 8, 13, 11, 20, 5, 4 >, Sv2=< 36 >, Sd2=<>
€ k < |Sg2| ’ selection(Sg2, 4)
selection(Sg2,4) : V3=5, Sg3=< 4 > , Sv3=< 5, 5 > , Sd3=< 21, 8, 13, 11, 20 >
€ k > |Sg3| + |Sv3| ’ selection(Sd3, 4 - |Sg3| + |Sv3|) = selection(Sd3, 1)
selection(Sd3,1) : V4=21, Sg4=< 8, 13, 11, 20 > , Sv4=< 21 > , Sd4=<>
€ k < |Sg4| ’ selection(Sg4, 1)
selection(Sg4,1) : V5=8, Sg5=<> , Sv5=< 8 > , Sd5=< 13, 11, 20 >
€ |Sg5| < k |Sg5| + |Sv5| car 0 < 1 1
€ le résultat est = V5 = 8
€ Il y a bien 5 éléments < 8 et 5 éléments 8
Paramètre formel à valeur par défaut des fonctions #49
servir_cafe ()
# On s e r t un c a f é noir
s e r v i r _ c a f e ( t a i l l e = ’ double ’ )
# On s e r t un c a f é n o i r double
• Sous Python, les paramètres (formels) à valeur par défaut sont nommés. Ces noms permettent de passer les argu-
ments dans un ordre quelconque (on a vu un exemple plus haut).
• En Python, la combinaison des valeur par défaut et le nom pour un paramètre permettent d’appeler les fonctions
avec plus de souplesse, sans que l’utilisation des noms soit une obligation.
Un autre exemple :
d e f l o g ( message=None ) :
i f message :
p r i n t ( " { 0 } " . f o r m a t ( message ) )
• On peut appeler cette fonction avec un argument (qui peut être None).
l o g ( " F i c h i e r ferm é " )
# F i c h i e r ferm é
l o g ( None )
#
• Mais on peut l’appeler sans argument auquel cas, la valeur par défaut joue son rôle (ici None) :
log ( )
#
function (1)
# Donne 1
function (2)
# Donne 1 ,2 ]
# !!!
Nombre variable de paramètres d’une fonction #50
function (1)
# prints ’ [1] ’
function (2)
# p r i n t s ’ [ 2 ] ’ , as expected
+ Ce comportement semble bizarre car normalement, stuff contient [1] après le 1er appel. Pourtant, le test sur
stuff fait au début est pour savoir si on a appelé la fonction sans donner ce paramètre (et None n’est pas mutable).
Donc, le test (if stuff is None) réussit et nous permet de savoir si le 2e paramètre a été fourni ou non.
do_something ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 )
# Donne ’ 1 , 2 , 3 , ( 4 , 5 , 6 , 7 , 8 , 9 ) ’
• On peut également avoir une nombre quelconque de clé-valeur (voir les Dicts) comme paramètre. Une fois
qu’on aura défini tous les autres paramètres, on utilise une variable précédée de ’**’ : soit **V. Python utilisera tout
le reste des paramètres clé-valeurs et les place dans une dict et l’affecte à V.
d e f do_something_else ( a , b , c , * args , * * kwargs ) :
p r i n t ( a , b , c , args , kwargs )
do_something_else ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , t i m e o u t = 1 . 5 )
# Donne ’ 1 , 2 , 3 , ( 4 , 5 , 6 , 7 , 8 , 9 ) , { " t i m e o u t " : 1 . 5 } ’
• Un problème se pose dans les paramètres par défaut et paramètres nommés. On définit une fonction et des
paramètres nommés.
d e f do_something ( a , b , c , a f f i c h e r = True , * args ) :
i f afficher :
p r i n t ( a , b , c , args )
do_something ( 1 , 2 , 3 , 4 , 5 , a f f i c h e r = True )
# ERREUR : TypeError : do_something ( ) g o t m u l t i p l e v a l u e s f o r paramè t r e ’ afficher ’
do_something ( 1 , 2 , 3 , a f f i c h e r = True , 4 , 5 , 6 )
# ERREUR S y n t a x E r r o r : non keyword arg a f t e r keyword arg
• Le problème : il n’y a pas de moyen pour spécifier afficher comme un paramètre clé-valeur tout en four-
nissant des paramètres autres.
Ÿ La seule solution pour passer afficher ici est d’utiliser un paramètre non clé-valeur.
do_something ( 1 , 2 , 3 , True , 4 , 5 , 6 )
# Ré s u l t a t : 1 , 2 , 3 , ( 4 , 5 , 6 )
Nombre variable de paramètres d’une fonction #51
"""
Test1 ( 1 , 2 , 3 )
Test1
1
2
3
Test1 ( 1 , b =3)
Test1
1
b = 3
XXIII-2 Passer des paramètres par défaut d’une fonction à une autre
• Un exemple :
d e f f u n c ( foo , bar=None , * * kwargs ) :
pass # On dé f i n i r a c e t t e f o n c t i o n p l u s t a r d !
....
#Appel :
desVars =1 ,2 ,3
f u n c ( 4 2 , bar =314 , e x t r a =desVars ) # e x t r a e s t un mot r é s e r v é
• Un autre exemple : on réceptionne les paramètres en utilisant * et ** dans les paramètres de la fonction. On peut
passer ces paramètres comme des paramètres d’appel d’une autre fonction.
d e f f ( x , * args , * * kwargs ) :
...
kwargs [ ’ w i d t h ’ ] = ’ 14.3 c ’
...
g ( x , * args , * * kwargs )
Listes en Compréhension #52
• La liste en compréhension souligne l’aspect fonctionnel de Python, en particulier avec map, filter et reduce 4 et le
expressions-lambda.
• Ce mécanisme procure un moyen rapide et compacte pour créer des listes. La liste en compréhension est davantage
préconisée en Python 3.4 à cause des modifications sur map et filter (qui sont devenus des générateurs).
• La liste en compréhension permet une traduction quasi directe des intensions. Soit :
S = {x2 : x 2 {0...9}}
V = (1, 2, 4, 8, ..., 212 )
M = {x|x 2 S ^ even(x)} avec even(x) : x = 2k, k 2 N
p r i n t ( S) ; p r i n t ( V ) ; p r i n t (M)
# [ 0 , 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 ]
# [ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ]
# [ 0 , 4 , 16 , 36 , 64 ]
+ On a demandé les résultats sous forme de listes. En utilisant des () à la place des [], on obtiendrait ici un générateur
(mais ce ne sera plus une liste en compréhension !). Notons également que {} sont utilisées pour les Sets et les Dicts
et les ’()’ également pour les tuples.
• On peut mieux comprendre les listes en compréhension à travers leurs fonctions équivalentes :
S = []
f o r i i n range ( 1 0 ) :
S . append ( i * 2 )
# Et
S = [ i * 2 f o r i i n range ( 1 0 ) ]
S
# [ 0 , 2 , 4 , 6 , 8 , 10 , 12 , 14 , 16 , 18 ]
• Ou encore
M = []
f o r i i n range ( 1 0 ) :
i f ( i % 2 == 0 ) :
M. append ( i )
# Et
M = [ i f o r i i n range ( 1 0 ) i f i % 2 == 0 ]
M
# [ 0, 2, 4, 6, 8]
p
Ÿ La valeur 8 correspond à int( 50) + 1.
4. Utiliser, comme dans l’exemple, functools.reduce(). Il est fortement conseillé d’utiliser une boucle for à la place.
Listes en Compréhension #53
# Donne [ ’ f ’ , ’ o ’ , ’ o ’ , ’ b ’ , ’ a ’ , ’ r ’ ]
Ÿ L’expression [c for c in "foobar"] est, du fait de la présence des ’[]’, équivalente à list("foobar").
• Une autre liste en compréhension pour construire une liste des caractères :
t e x t e = " La m e i l l e u r e f a çon de marcher . . . "
[ t e x t e [ i ] f o r i i n range ( l e n ( t e x t e ) ) ]
# Donne : [ ’ L ’ , ’ a ’ , ’ ’ , ’m ’ , ’ e ’ , ’ i ’ , ’ l ’ , ’ l ’ , ’ e ’ , ’ u ’ , ’ r ’ , ’ e ’ , ’ ’ , ’ f ’ , ’a ’ , ’ç ’ , ’o ’ , ’n ’ , ’ ’ , ’d
’ , ’ e ’ , ’ ’ , ’m ’ , ’ a ’ , ’ r ’ , ’ c ’ , ’ h ’ , ’ e ’ , ’ r ’ , . . . ]
D’autres exemples :
liste_origine = [ 0, 1, 2, 3, 4, 5]
[ nb * nb f o r nb i n l i s t e _ o r i g i n e ]
#==> [ 0 , 1 , 4 , 9 , 16 , 25 ]
# L i r e 10 f o i s l e c l a v i e r e t f a i r e un e l i s t e :
L= [ i n p u t ( " une chose " ) f o r i i n range ( 1 0 ) ]
# Copie d ’ une l i s t e
l l = [ 1 ,2 ,3 ]
i n v = [ l l [ i ] f o r i i n range ( 3 ) ]
• L’expression de la liste en compréhension peut contenir des filtres (tests, appels de fonctions, etc) :
l i s t e _ o r i g i n e = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ]
[ nb f o r nb i n l i s t e _ o r i g i n e i f nb % 2 == 0 ]
# ==> [ 2 , 4 , 6 , 8 , 10 ]
#
d e f pa s_ mu l ti p l e _d e_6 ( x ) : r e t u r n x % 2 ! = 0 and x % 3 ! = 0
[ i f o r i i n range ( 2 , 25) i f pas _m ul t i p l e_ de _6 ( i ) ]
# Donne : [ 5 , 7 , 11 , 13 , 17 , 19 , 23 ]
#
d e f cube ( x ) : r e t u r n x * x * x
• En Python 3, la liste en compréhension vient remplacer map et filter (voir plus loin).
# S i l e f i c h i e r n ’ e x i s t e pas , on a l ’ e r r e u r ( e x c e p t i o n ) :
# OS e r r o r : [ Errno 2 ] No such f i l e o r d i r e c t o r y : ’ f i c t e s t 1 . t x t ’
# Et ’ r a i s e ’ c e l a donnera
# F i l e N o t F o u n d E r r o r : [ Errno 2 ] No such f i l e o r d i r e c t o r y : ’ fic tes1t . t x t ’
try :
f = open ( ’ m y f i l e . t x t ’ )
s = f . readline ()
i = int (s. strip () )
except OSError as e r r :
p r i n t ( "OS e r r o r : { 0 } " . f o r m a t ( e r r ) )
except V a l u e E r r o r : # Pour l ’ e r r e u r de c o n v e r s i o n
p r i n t ( " Conversion en e n t i e r i m p o s s i b l e . " )
except : # Autre e r r e u r
p r i n t ( " E r r e u r ? : " , sys . e x c _ i n f o ( ) [ 0 ] )
raise # On r e l ève l ’ e x c e p t i o n pou r l e niveau e ng l o b an t .
# split(sep)
a= " C e t t e phrase , d e v i e n t , , une \ t l i s t e "
b=a . s p l i t ( " , " )
print (b)
# [ ’ C e t t e phrase ’ , ’ d e v i e n t ’ , ’ une \ t l i s t e ’ ]
+ Un truc :
Si vous voulez lire une série d’entiers sur une ligne :
s e r i e = map( i n t , i n p u t ( ) . s t r i p ( ) . s p l i t ( " " ) )
f . __enter__ ( ) # La mé thode de l a c l a s s e
#< _ i o . TextIOWrapper name= ’ f i c t e s t . t x t ’ mode= ’ r ’ encoding = ’UTF 8’>
f . read ( 1 ) # L i r e un c a r a c t è r e
# ’E ’
Avec with, c’est plus simple : pour ouvrir le fichier, traiter son contenu (ça, c’est nous qui le faisons !) et de le
fermer à la fin.
w i t h open ( " f i c t e s t . t x t " ) as f :
data = f . read ( )
# t r a i t e r l e s données , par exemple :
p r i n t ( data )
• with et split() :
w i t h open ( ’ data . t x t ’ , ’ r ’ ) as f :
data = f . r e a d l i n e s ( )
f o r l i n e i n data :
words = l i n e . s p l i t ( )
p r i n t ( words )
# Et s i vous v o u l e z chaque c a r a c t è r e de ’ words ’ , f a i t e s comme pour l e s l i s t e s .
V o i r e a u s s i l ’ e x e r c i c e 561.
# Un ggéné r a t e u r
lignes_non_vides = ( l i n e f o r l i n e in f i f line . strip () )
mot = " E x t r a i r e "
# Un géné r a t e u r
l i g n e s _ q u i _ c o n t i e n n e n t _ m o t = ( l f o r l i n l i g n e s _ n o n _ v i d e s i f mot i n l )
p r i n t ( lignes_qui_contiennent_mot )
# < g e n e r a t o r o b j e c t <genexpr > a t 0x7f291d512ee8 >
# Un géné r a t e u r
l i g n e s _ q u i _ n e _ f i n i s s e n t _ p a s _ p a r _ u n _ p o i n t = ( l f o r l i n l i g n e s _ q u i _ c o n t i e n n e n t _ m o t i f n o t l . endswith ( ’ . ’ ) )
# On r écupè r e l a l i s t e a s s o c i ée à un géné r a t e u r
lignes_numerotees = l i s t ( enumerate ( l i g n e s _ q u i _ n e _ f i n i s s e n t _ p a s _ p a r _ u n _ p o i n t ) )
p r i n t ( lignes_numerotees )
# [ (0 , ’ E x t r a i r e l e s nombres \ n ’ ) ]
f . close ( )
+ Remarques :
• Noter bien que readline renvoie la chaîne vide ” après EOF, pas d’exception.
• On peut essayer en testant vs ” ou utiliser strip() pour déceler les lignes vides : ligne.strip() réussit si ligne
n’est pas vide.
• Noter que ligne=readline() conserve ’\n’.
• Pour trouver un ’.’ à la fin de ligne (qui contient ’\n’), on peut tester if ligne.endswith(’.\n’).
XXV-6 Exercice
• Lire un fichier et extraire :
La fréquence des mots
La fréquence des lettres
Le nombre de phrases (terminant avec un ’.’)
Les nombres
Ÿ Le passage par la fonction ord(x) est ici obligatoire. ord(x) renvoie un entier pour un caractère contenant un
chiffre.
Si on doit nommer le range du champ à formater (ici 0:...) :
s t = " h e l l o Debase "
p r i n t ( ’ ’ . j o i n ( [ " { 0 : b } " . f o r m a t ( ord ( x ) ) f o r x i n s t ] ) )
# 1101000 1100101 1101100 1101100 1101111 100000 1000100 1100101 1100010 1100001 1110011 1100101
s . center (10 , " * " ) # centrer sur 10 positions en complétant par des ’*’
# Donne >’** Python * * ’
+ En fait, str.ljust(n) construit une nouvelle chaîne de taille n à partir de str en plaçant str à gauche de cette nouvelle
chaîne. De même pour str.rjust(n) et str.center(n).
Compléments sur la mise en page #58
• Exemples :
s = ’ Hello , world . ’
str (s)
# Donne >’H e l l o , w o r l d . ’
repr ( s )
# Donne > " ’ Hello , world . ’ "
str (1/7)
# Donne > ’0.14285714285714285 ’
x = 10 * 3.25
y = 200 * 200
s = ’ The v a l u e o f x i s ’ + r e p r ( x ) + ’ , and y i s ’ + r e p r ( y ) + ’ . . . ’
print (s)
# Donne > The v a l u e o f x i s 3 2 . 5 , and y i s 4 0 0 0 0 . . .
+ Remarques : Si vous souhaitez terminer chaque écriture par autre chose qu’un retour charriot, utilisez l’ar-
gument end=... dans l’appel de print. Par défaut, end=’\n’.
Par exemple :
f o r x i n range ( 1 , 6 ) :
p r i n t ( r e p r ( x ) . r j u s t ( 2 ) , end= ’ # ’ * x+ ’ \ n ’ ) on ajoute x fois # + \n à la fin de chaque ligne
# Donne >
1#
2##
3###
4####
5#####
• L’intérêt de end=... se trouve souvent dans les cas où on a deux ordres print et on voudrait que le deuxième
soit à la suite du premier.
p r i n t ( 1 , 2 , end= ’ ’ ) # Ne pas passer à l a l i g n e pour que . . .
x= f o n c t i o n _ q u i _ c a l c u l e ( 3 ) # . . . la
print (x) # . . . v a l e u r de x s ’ a f f i c h e à l a s u i t e s u r l a même l i g n e
Gestion du temps #59
p r i n t ( "%2d " * 8 % X )
# 0 1 2 3 4 5 6 7
[ p r i n t ( "%2d " % i ) f o r i i n X ]
• Pour une exécution en ligne de commande d’une fonction my_fonction() que l’on aurait définie dans le module
my_module et mesurer le temps, on peut écrire :
$ python3 . 4 m timeit s "import my_module as my_mo_sa" "my_mo_sa.my_fonction()"
• On peut également utiliser la fonction time.time() pour mesurer le temps d’exécution d’une fonction :
from t i m e i m p o r t t i m e
d e f count ( ) :
deb = t i m e ( )
[ x f o r x i n range (10000000) i f x%4 == 1 ]
f i n = time ( )
p r i n t ( f i n deb )
count ( )
# 1.213
Ÿ Il est conseillé d’utiliser timeit (exemple ci-dessus) à la place de time car timeit est plus juste et tient compte du
ramassage des miettes (gc : garbage collector).
Gestion du temps #60