Cours Python3 Mars 2026
Cours Python3 Mars 2026
CHAPITRE 1
NOTIONS DE BASE
Dans la technique de l’interprétation chaque ligne du code source analysé est traduite au fur
et à mesure en instructions directement exécutées. Aucun programme objet n’est généré. Cette
technique est très souple mais les codes générés sont peu performants : l’interpréteur doit être
utilisé à chaque nouvelle exécution.. .
Pour exécuter un programme, Python charge le fichier source .py (ou .pyw) en mémoire vive,
en fait l’analyse (lexicale, syntaxique et sémantique), produit le bytecode et enfin l’exécute.
Afin de ne pas refaire inutilement toute la phase d’analyse et de production, Python
sauvegarde le bytecode produit (dans un fichier .pyo ou .pyc) et recharge simplement le fichier
bytecode s’il est plus récent que le fichier source dont il est issu.
En pratique, il n’est pas nécessaire de compiler explicitement un module, Python gère ce
mécanisme de façon transparente.
1.3 La construction des programmes
Le génie logiciel étudie les méthodes de construction des programmes. Plusieurs modèles sont
envisageables, entre autres :
Algorithme et programme
ii. Définitions
Définition
Algorithme : ensemble des étapes permettant d’atteindre un but en répétant un nombre fini
de fois un nombre fini d’instructions.
Un algorithme se termine en un temps fini.
Définition
Programme : un programme est la traduction d’un algorithme en un langage compilable ou
inter- prétable par un ordinateur.
Il est souvent écrit en plusieurs parties dont une qui pilote les autres : le programme principal.
La signification de parties non triviales (et uniquement celles-ci) doit être expliquée par un
commentaire. En Python, un commentaire commence par le caractère # et s’étend jusqu’à la fin
de la ligne :
#
# Voici un commentaire
#
9 + 2 # En voici un autre
Cette partie présente les règles de construction des identificateurs, les types
de données simples (les conteneurs seront examinés ultérieurement) ainsi que les
types chaîne de caractères.
Enfin, elle s’étend sur les notions non triviales de variable, de référence d’objet
et d’affectation.
Pour ne pas prêter à confusion, éviter d’utiliser les caractères l (minuscule), O et I (majuscules)
seuls.
Enfin, on évitera d’utiliser les notations suivantes :
_xxx # usage interne
xxx # attribut de classe
xxx # nom spécial réservé
Une expression est une portion de code que l’interpréteur Python peut évaluer pour
obtenir une valeur.
Les expressions peuvent être simples ou complexes. Elles sont formées d’une combinaison de
littéraux représentant directement des valeurs, d’identificateurs et d’opérateurs.
>>>
>>>
... else :
1. Voir les détails dans la PEP 8 : « Style Guide for Python », Guido van R. et Barry W.
7
Opérations arithmétiques
6
>>> 20 % 3 # modulo
Bases usuelles
Un entier écrit en base 10 (par exemple 179) peut se représenter en binaire, octal et hexadécimal
en utilisant les syntaxes suivantes :
>>> 0b10110011 # binaire
179
>>> bin(179)
'0b10110011'
>>> 0o263 # octal
179
>>> oct(179)
'0o263'
>>> 0xB3 # hexadécimal
179
>>> hex(179)
'0xb3'
1. Dans la plupart des autres langages les entiers sont codés sur un nombre fixe de bits et ont un domaine de
définition limité auquel il convient de faire attention.
8
>>> 2 > 8
False
>>> 2 <= 8 < 15
True
En Python les valeurs des variables booléennes sont notées False et True. Les
opérateurs sont notés respectivement not, and et or.
a not(a)
False True
True False
a b a or b a and b
Attention
Pour être sûr d’avoir un résultat booléen avec une expression reposant sur des valeurs
transtypées, appliquez bool() sur l’expression.
• Un float est noté avec un point décimal (jamais avec une virgule) ou en notation
exponentielle avec un « e» symbolisant le « 10 puissance » suivi des chiffres de
l’exposant. Par exemple :
2.718
.02
-1.6e-19
6.023e23
Définition
Une variable est un identificateur associé à une valeur. En Python, c’est une référence d’objet.
2.6.2 L’affectation
Définition
On affecte une variable par une valeur en utilisant le signe = (qui n’a rien à voir avec l’égalité
en math !). Dans une affectation, le membre de gauche reçoit le membre de droite ce qui
nécessite d’évaluerla valeur correspondant au membre de droite avant de l’affecter au membre
de gauche.
import math
a = 2
b = 7.2 * [Link](math.e / 45.12) - 2*[Link]
c = b ** a
Remarque
✓ À l’oral, au lieu de dire « a égal 2 », dites « a reçoit 2 ».
La valeur d’une variable, comme son nom l’indique, peut évoluer au cours du temps. La
valeur an térieure est perdue :
>>> a = 3 * 7
>>> a
21
>>> b = 2 * 2
>>> b
4
>>> a = b + 5
>>> a
9
Le membre de droite d’une affectation étant évalué avant de réaliser l’affectation elle-même, la
variable affectée peut se trouver en partie droite et c’est sa valeur avant l’affectation qui est
utilisée dans le calcul :
>>> a = 2
>>> a = a + 1 # incrémentation
>>> a
3
>>> a = a - 1 # décrémentation
>>> a
2
La comparaison a une valeur (de type bool) utilisable dans une expression mais n’a pas d’effet :
2.7.2 Opérations
• Longueur :
>>> s = "abcde"
>>> len(s)
5
• Concaténation :
>>> s1 = "abc"
>>> s2 = "defg"
>>> s3 = s1 + s2
>>> s3
'abcdefg'
• Répétition :
>>> s5 = s4 * 3
>>> s5
• istitle() : retourne True si seule la première lettre de chaque mot de la chaîne est en majuscule
>>> [Link]()
False
:
• isalnum(), isalpha(), isdigit() et isspace() :
retournent True si la chaîne ne contient respective ment
que des caractères alphanumériques, alphabétiques, numériques ou des espaces :
>>> [Link]()
True
>>> [Link]()
False
2.7 Les chaînes de caractères 13
• startswith(prefix[, start[, stop]]) et endswith(suffix[, start[, stop]]) : testent si la sous- chaîne définie par
start et stop commence respectivement par prefix ou finit par suffix:
>>> [Link]('cH')
True
>>> [Link]('aSSe')
False
• zfill(width) : complète ch à gauche avec des 0 jusqu’à une longueur maximale de width :
>>> [Link](20)
00000000cHAise basSe
• replace(old[, new[, count]]) : remplace count instances (toutes par défaut) de old par new:
>>> [Link]('HA', 'ha')
chaise basSe
• split(seps[, maxsplit]) :
découpe la chaîne en maxsplit morceaux (tous par défaut). rsplit() effectue la
même chose en commençant par la fin et striplines()effectue ce travail avec les caractères de
fin de ligne :
>>> [Link]()
['cHAise', 'basSe']
• join(seq) :
concatène les chaînes du conteneur seq en intercalant entre chaque élément la
chaîne sur laquelle la méthode est appliquée :
>>> "**".join(['cHAise', 'basSe'])
cHAise**basSe
2.7.6 Indexation simple
Pour indexer une chaîne, on utilise l’opérateur [ ] dans lequel l’index, un entier signé qui
commence à 0 indique la position d’un caractère :
Une donnée binaire contient une suite de zéro ou plusieurs octets, c’est-à-dire d’entiers non
signés sur 8 bits (compris dans l’intervalle [0…255]). Ces types « à la C » sont bien adaptés pour
stocker de grandes quantités de données. De plus Python fournit des moyens de manipulation
efficaces de ces types.
Les deux types sont assez semblables au type str et possèdent la plupart de ses méthodes.
Le type modifiable bytearray possède des méthodes communes au type list.
>>> a, b = 2, 5
>>> print(a, b)
2 5
>>> print("Somme :", a + b)
Somme 7
>>>> print(a - b, "est la différence")
-3 est la différence
>>> print("Le produit de", a, "par", b, "vaut :", a * b)
Le produit de 2 par 5 vaut 10
>>> print()
2@5
Séquence Signification
\saut_ligne saut de ligne ignoré (en fin de ligne)
\\ affiche un antislash
\' apostrophe
\" guillemet
\a sonnerie (bip)
\b retour arrière
\f saut de page
\n saut de ligne
\r retour en début de ligne
\t tabulation horizontale
\v tabulation verticale
\N{nom} caractère sous forme de code Unicode
nommé
\uhhhh caractère sous forme de code Unicode 16
bits
\Uhhhhhhhh caractère sous forme de code Unicode 32
bits
\ooo caractère sous forme de code octal
\xhh caractère sous forme de code hexadécimal
Exemples :
Un script Python est formé d’une suite d’instructions exécutées en séquence de haut en bas a.
Chaque ligne d’instructions est formée d’une ou plusieurs lignes physiques qui
peuvent être continuées par un antislash \ou un caractère ouvrant [({pas encore
fermé.
Cette exécution en séquence peut être modifiée pour choisir ou répéter des
portions de code, ce que l’on appelle des « instructions composées ».
a. On peut mettre plusieurs instructions sur la même ligne en les séparant avec un « ; »
mais, par soucis de lisibilité, c’est déconseillé.
Attention
Toutes les instructions au même niveau d’indentation appartiennent au même bloc (☞ Fig. 3.1).
Exemple :
>>> # ...
...
>>> n = -3
>>> if n < 0:
... print("Votre nombre est négatif.")
...
Votre nombre est négatif.
>>> # ... suite du programme
>>> if n <= 0:
... print("Votre nombre est négatif ou nul.")
... else :
... print("Votre nombre est positif.")
... if n > 2:
... print("Il est supérieur à 2.")
...
Votre nombre est positif.
Il est supérieur à 2.
>>> # ... suite du programme
3.2 Choisir
3.2.1 Choisir : if - [elif] - [else]
Contrôler une alternative :
>>> x = 5
>>> if x < 0:
... print("x est négatif. Pour sa valeur absolue, on prend l'opposé")
... elif x % 2:
... print("x est positif et impair")
... else :
... print("x n'est pas négatif et est pair")
...
x est positif et impair
>>> x, y = 4, 3
>>> if x < y : # écriture classique
... plus_petit = x
... else :
... plus_petit = y
...
>>> print("Plus petit : ", plus_petit)
Plus petit 3
>>>
>>> plus_petit = x if x < y else y # utilisation de l'opérateur ternaire
19
Remarque
✓ L’opérateur ternaire est une expression qui fournit une valeur que l’on peut utiliser dans une
affectation ou un calcul.
3.3 Boucles
Répéter une portion de code tant qu’une expression booléenne est vraie :
Utilisation classique : la saisie filtrée d’une valeur numérique (on doit préciser le type car on
se rappelle que input() saisit une chaîne) :
Parcourir un itérable :
a
3.14
>>> for i in range(5) :
... print(i)
...
0
>>>
>>> nb_voyelles = 0
>>> for lettre in "Python est un langage tres sympa" :
... if lettre in "aeiouy" :
... nb_voyelles = nb_voyelles + 1
...
>>> nb_voyelles
10
while - else
Les boucles while et for peuvent posséder une clause else qui ne s’exécute que si la boucle se
termine normalement, c’est-à-dire sans interruption :
x = y // 2
while x > 1:
if y % x == 0:
print(x, "a pour facteur", y)
break # voici l'interruption !
3.4 Ruptures de séquences 21
x -= 1
else :
print(y, "est premier.")
for - else
for i in une_sequence :
if i == cible :
sauve = i
break # voici l'interruption !
else :
print(cible, "n'est pas dans", une_sequence)
sauve = None
Toutes les exceptions levées par Python appartiennent à un ensemble d’exceptions nommé Exception.
Cette famille offre une vingtaine d’exceptions standard 1.
try :
... # séquence normale d'exécution
except <exception_1> as e1 :
... # traitement de l'exception 1
except <exception_2> as e2 :
... # traitement de l'exception 2
...
1. Citons quelques exemplaires : AritmeticError, ZeroDivisionError, IndexError, KeyError, AttributeError, IOError, ImportEr-ror, NameError,
SyntaxError, TypeError. . .
22 Le contrôle du flux d’instructions
else :
... # clause exécutée en l'absence d'erreur
finally :
... # clause toujours exécutée
x = 2
if not(0 <= x <= 1) :
raise ValueError("x n'est pas dans [0 .. 1]")
Remarque
✓ raise, sans valeur, dans un bloc except, permet de ne pas bloquer une exception et de la
propager.
CHAPITRE 3
>>> truc = []
>>> machin = [0.0] * 3
>>> truc
[]
>>> machin
[0.0, 0.0, 0.0]
>>>
>>> liste_1 = list(range(4))
>>> liste_1
[0, 1, 2, 3]
>>> liste_2 = list(range(4, 8))
>>> liste_2
[4, 5, 6, 7]
>>> liste_3 = list(range(2, 9, 2))
>>> liste_3
[2, 4, 6, 8]
>>>
>>> 2 in liste_1, 8 in liste_2, 6 in liste_3
(True, False, True)
4.2.3 Méthodes
Quelques méthodes de modification des listes :
a
b
c
d
i = 1
msg = "Quoi de neuf ?"
e = 2.718
Une conséquence de ce mécanisme est que, si un objet modifiable est affecté à plusieurs
variables, tout changement de l’objet via une variable sera visible sur tous les autres :
phrase[4] = "casse"
Si on veut pouvoir effectuer des modifications séparées, il faut affecter l’autre variable par une
copie distincte de l’objet, soit en créant une tranche complète des séquences dans les cas simples,
soit en utilisant le module copy dans les cas les plus généraux (autres conteneurs). Dans les rares
occasions où l’on veut aussi que chaque élément et attribut de l’objet soit copié séparément et
de façon récursive, on emploie la fonction [Link]():
>>> import copy
>>> a = [1, 2, 3]
>>> b = a # une référence
>>> [Link](4)
>>> a
[1, 2, 3, 4]
>>> c = a[:] # une copie simple
>>> [Link](5)
>>> c
[1, 2, 3, 4, 5]
>>> d = [Link](a) # une copie de "surface"
>>> [Link](6)
>>> d
[1, 2, 3, 4, 6]
>>> a
[1, 2, 3, 4]
>>> d1 = {'a' : [1, 2], 'b' : [3, 4]}
>>> d2 = {'c' : (1, 2, 3), 'c' : (4, 5, 6)}
>>> liste_de_dicos = [d1, d2]
>>> nouvelle_liste_de_dicos = [Link](liste_de_dicos) # copie "profonde" (ou "récursive")
>>> nouvelle_liste_de_dicos
[{'a' : [1, 2], 'b' : [3, 4]}, {'c' : (4, 5, 6)}]
• Assignation augmentée d’un objet modifiable (cas d’une liste : ☞ Fig. 4.2). On a
représenté l’étape de la création de la liste intermédiaire.
27
Les dictionnaires constituent un type composite mais ils n’appartiennent pas aux séquences.
Comme les listes, les dictionnaires sont modifiables, mais les couples enregistrés n’occupent pas un
ordre immuable, leur emplacement est géré par un algorithme spécifique.
Une clé pourra être alphabétique, numérique.. . en fait tout type hachable (donc liste et
dictionnaire exclus). Les valeurs pourront être de tout type sans exclusion.
Exemples de création
Méthodes
Quelques méthodes applicables aux dictionnaires :
>>> tel = {'jack' : 4098, 'sape' : 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape' : 4139, 'jack' : 4098, 'guido' : 4127}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'jack' : 4098, 'irv' : 4127, 'guido' : 4127}
>>>
>>> [Link]()
['jack', 'irv', 'guido']
>>> sorted([Link]())
['guido', 'irv', 'jack']
>>> sorted([Link]())
[4098, 4127, 4127]
>>> 'guido' in tel, 'jack' not in tel
(True, False)
>>> X = set('abcd')
>>> Y = set('sbds')
>>> X
set(['a', 'c', 'b', 'd'])
>>> Y
set(['s', 'b', 'd'])
>>> 'c' in X
True
>>> 'a' in Y
False
>>> X - Y
set(['a', 'c'])
>>> Y - X
set(['s'])
>>> X | Y
29
Nous limiterons nos exemples aux fichiers textuels (lisibles par un éditeur), mais signalons
que les fichiers stockés en codage binaire sont plus compacts et plus rapides à gérer (utiles pour
les grands volumes de données).
Python utilise les fichiers en mode texte par défaut (mode t). Pour les fichiers binaires, il faut
préciser le mode b.
Le paramètre optionnel encoding assure les conversions entre les types byte, stocké dans
le fichier sur le disque, et le type str, manipulé lors des lectures et écritures.
Les encodages les plus fréquents sont 'utf8' (c’est l’encodage à privilégier en Python 3),
'latin1', 'ascii'. . .
Tant que le fichier n’est pas fermé 1, son contenu n’est pas garanti sur le
[Link]()
Écriture séquentielle
Le fichier sur disque est considéré comme une séquence de caractères qui sont ajoutés à la
suite, au fur et à mesure que l’on écrit dans le fichier.
Méthodes d’écriture :
f = open("[Link]", "w")
s = 'toto\n'
[Link](s) # écrit la chaîne s dans f
l = ['a', 'b', 'c']
[Link](l) # écrit les chaînes de la liste l dans f
[Link]()
f2 = open("[Link]", "w")
print("abcd", file=f2) # utilisation de l'option file
[Link]()
Lecture séquentielle
En lecture, la séquence de caractères qui constitue le fichier est parcourue en commençant au
début du fichier et en avançant au fur et à mesure des lectures.
Méthodes de lecture :
f = open("[Link]", "r")
s = [Link]() # lit tout le fichier --> chaîne
s = [Link](3) # lit au plus n octets --> chaîne
s = [Link]() # lit la ligne suivante --> chaîne
s = [Link]() # lit tout le fichier --> liste de chaînes
[Link]()
Obtenir une séquence triée à éléments uniques (la séquence initiale est inchangée) :
basket = ["apple", "orange", "apple", "pear", "orange", "banana"]
for f in sorted(set(basket)) :
print(f, end=" ") # apple banana orange pear
Formatages numériques :
s = "int :{0:d} ; hex : {0:x} ; oct : {0:o} ; bin : {0:b}".format(42)
print(s) # int :42; hex : 2a ; oct : 52; bin : 101010
s = "int :{0:d} ; hex : {0:#x} ; oct : {0:#o} ; bin : {0:#b}".format(42)
print(s) # int :42; hex : 0x2a ; oct : 0o52 ; bin : 0b101010
n = 100
pi = 3.1415926535897931
k = -54
print("{ :+d} { :+d}".format(n, k)) # +100 -54 (on force l'affichage du signe)
1. str() est un affichage orienté utilisateur alors que repr() est une représentation littérale.
32 Les conteneurs standard
Les fonctions sont les éléments structurants de base de tout langage procédural.
Ces avantages sont illustrés sur la figure 5.1 qui utilise entre autres la notion d’import,
mé- canisme très simple qui permet de réutiliser des fichiers de fonctions, souvent
appelés modules ou bibliothèques.
Figure 5.2 – Passage des arguments par affectation des paramètres aux arguments.
# exemple d'appel :
table(7, 2, 8)
# 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35 6 x 7 = 42 7 x 7 = 49 8 x 7 = 56
def cube(x) :
"""Retourne le cube de largument."""
return x**3
def volumeSphere(r) :
"""Retourne le volume d'une sphère de rayon <r> ;"""
return 4.0 * pi * cube(r) / 3.0
1. Une fonction vaut quelque chose, une procédure fait quelque chose.
36 Fonctions et espaces de noms
import math
def surfaceVolumeSphere(r) :
surf = 4.0 * [Link] * r**2
vol = surf * r/3
return surf, vol
# programme principal
rayon = float(input('Rayon : '))
s, v = surfaceVolumeSphere(rayon)
print("Sphère de surface { :g} et de volume { :g}".format(s, v))
>>> h(g, 4)
Attention
🖂 On utilise de préférence des valeurs par défaut non modifiables (int, float, str, bool, tuple) car
la modification d’un paramètre par un premier appel est visible les fois suivantes.
Si on a besoin d’une valeur par défaut qui soit modifiable (list, dict), on utilise la valeur
prédéfinie
None et on fait un test au début de la fonction :
def maFonction(liste=None) :
if liste is None :
liste = [1, 3]
5.3 Espace
s de noms 37
# Exemples d'appel :
print(somme(23)) # 23
print(somme(23, 42, 13)) # 78
Attention
# Exemple d'appel :
elements = (2, 4, 6)
print(somme(*elements)) # 12
# Exemples d'appels
## par des paramètres nommés :
print(unDict(a=23, b=42)) # {'a' : 23, 'b' : 42}
## en fournissant un dictionnaire :
mots = {'d' : 85, 'e' : 14, 'f' :9}
print(unDict(**mots)) # {'e' : 14, 'd' : 85, 'f' : 9}
Attention
🖂 Si la fonction possède plusieurs arguments, le dictionnaire est en toute dernière
position (après un éventuel tuple).
Exemples de portée
Par défaut, toute variable utilisée dans le corps d’une fonction est locale à celle-ci. Si une
fonction a besoin de modifier certaines variables globales, la première instruction de cette
global <identificateurs>
x = 99
print(fonc(1)) # 102
print(x) # 101
x = 99
print(fonc(1)) # 100
print(x) # 99
x = 99
print(fonc(1)) # 4
print(x) # 99
CHAPITRE 6
Modules et packages
6.1 Modules
Définition
Module : fichier script Python permettant de définir des élements de programme réutilisables. Ce
mécanisme permet d’élaborer efficacement des bibliothèques de fonctions ou de classes.
Remarque
✓ Lorsqu’on parle du module, on omet l’extention : le module machin est dans le fichier [Link] ou
[Link].
6.1.1 Import
L’instruction importcharge et exécute le module indiqué s’il n’est pas déjà chargé. L’ensemble des
défini- tions contenues dans ce module deviennent alors disponibles : variables globales,
fonctions, classes.
Suivant la syntaxe utilisée, on accède aux définitions du module de différentes façons :
• l’instruction from <nom_module> import nom1, nom2. . . donne accès directement à une
sélection choisie de noms définis dans le module.
>>> from math import pi, sin
>>> print("Valeur de Pi :", pi, "sinus(pi/4) :", sin(pi/4))
Valeur de Pi : 3.14159265359 sinus(pi/4) : 0.707106781187
Dans les deux cas, le module et ses définitions existent dans leur espace mémoire propre, et on
duplique simplement dans le module courant les noms que l’on a choisi, comme si on avait fait les
affectations :
>>> sin = [Link]
>>> pi = [Link]
Remarque
✓ Il est conseillé d’importer dans l’ordre :
• les modules de la bibliothèque standard ;
• les modules des bibliothèques tierces ;
• Les modules personnels.
Attention
🖂 Pour tout ce qui est fonction et classe, ainsi que pour les « constantes » (variables globales
définies et affectée une fois pour toute à une valeur), l’import direct du nom ne pose pas de
problème.
Par contre, pour les variables globales que l’on désire pouvoir modifier, il est préconisé de
passer systématiquement par l’espace de nom du module afin de s’assurer de l’existence de
cette variable en un unique exemplaire ayant la même valeur dans tout le programme.
6.1.2 Exemples
Notion d’« auto-test »
Le module principal est celui qui est donné en argument sur la ligne de commande ou qui est
lancé en premier lors de l’exécution d’un script. Son nom est contenu dans la variable globale
name . Sa valeur dépend du contexte de l’exécution.
Soit le module :
# je_me_nomme.py
print("Je me nomme :", name )
Premier contexte exécution sur la ligne de commande (ou dans un EDI), on obtient la valeur
prédéfinie
main :
$ python3 je_me_nomme.py
Je me nomme : main
Second contexte import de ce module (ce n’est donc plus le module principal ), on obtient
l’identificateur du module :
>>> import je_me_nomme
Je me nomme : je_me_nomme
Grâce à un test, on peut donc facilement savoir si le code est exécuté en tant que script
principal :
# cube_m.py
def cube(x) :
"""retourne le cube de <x>."""
return x**3
# auto-test ===================================================================
if name == " main " : # vrai car module principal
print("OK !") if cube(9) == 729 else "KO !"
6.2 Bibliothèque standard 41
Utilisation de ce module :
import cube_m
"""
cube de 1 = 1
cube de 2 = 8
cube de 3 = 27
"""
Autre exemple :
def ok(message) :
"""
Retourne True si on saisie <Entrée>, <O>, <o>, <Y> ou <y>,
False dans tous les autres cas.
"""
s = raw_input(message + " (O/n) ? ")
return True if s == "" or s[0] in "OoYy" else False
# auto-test ===================================================================
if name == ' main ' :
import sys
while True :
if ok("Encore") :
print("Je continue")
else :
[Link]("Je m'arrête")
"""
Encore (O/n) ?
Je continue
Encore (O/n) ? o
Je continue
Encore (O/n) ? n
Je m'arrête
"""
Le module [Link]
Ce module fournit des objets compatibles avec l’interface des objets fichiers.
Exemple de gestion ligne à ligne d’un fichier ou d’une chaîne avec la même fonction scanner()
utilisant le même traitement dans les deux cas :
fic = open("[Link]")
scanner(fic, premierMot)
import io
chaine = [Link]("un\ndeux xxx\ntrois\n")
scanner(chaine, premierMot)
python 6_025.py -h
ou
python 6_025.py --help
Options :
-h, --help show this help message and exit
-f FILE, --file=FILE write report to FILE
-q, --quiet don't print status messages to stdout
0.4266274931268761
>>> [Link](3, 4)
5.0
>>> [Link](1)
57.29577951308232
[Link]().prec = 6
print([Link](1) / [Link](7)) # 0.142857
[Link]().prec = 18
print([Link](1) / [Link](7)) # 0.142857142857142857
En plus des bibliothèques math et cmath déjà vues, la bibliothèque random propose plusieurs
fonctions de nombres aléatoires.
vendredi_precedent = [Link]()
un_jour = [Link](days=1)
while vendredi_precedent.weekday() != [Link] :
vendredi_precedent -= un_jour
print(vendredi_precedent.strftime("%A, %d-%b-%Y"))
# Friday, 09-Oct-2009
heap = []
import collections
for i in range(10) :
[Link](heap,
# description du type :[Link](2, 9))
Point = [Link]("Point", "x y z")
print(heap) # [2, 3, 5, 4, 6, 6, 7, 8, 7, 8]
# on instancie un point :
point = Point(1.2, 2.3, 3.4)
# on l'affiche :
print("point : [{}, {}, {}]"
.format(point.x, point.y, point.z)) # point : [1.2, 2.3, 3.4]
À l’instar des structures C, Python propose désormais, via le module collections, la notion de
type tuple nommé :
44 Modules et packages
s = [('y', 1), ('b', 2), ('y', 3), ('b', 4), ('r', 1)]
d = defaultdict(list)
for k, v in s :
d[k].append(v)
print([Link]())
# dict_items([('y', [1, 3]), ('r', [1]), ('b', [2, 4])])
s = 'mississippi'
d = defaultdict(int)
for k in s :
d[k] += 1
print([Link]())
# dict_items([('i', 4), ('p', 2), ('s', 4), ('m', 1)])
Elle permet de calculer en tenant compte des unités du système SI (Système International
d’unités).
Voici un exemple de session interactive :
Définition
Un package est un module contenant d’autres modules. Les modules d’un package peuvent être
des sous-packages, ce qui donne une structure arborescente.
Chaque répertoire du paquet doit posséder un fichier init qui peut soit être vide soit
contenir du code d’initialisation.
CHAPITRE 7
7.1 Terminologie
Le vocabulaire de base de la POO
Une classe est équivalente à un nouveau type de données. On connaît déjà par exemple les classes
list
ou str et les nombreuses méthodes permettant de les manipuler, par exemple :
• [3, 5, 1].sort()
• "casse".upper()
Un objet ou une instance est un exemplaire particulier d’une classe. Par exemple [3, 5, 1]
est une instance de la classe listet "casse"est une instance de la classe str.
Les objets ont généralement deux sortes d’attributs : les données nommées simplement
attributs et les fonctions applicables appelées méthodes.
Par exemple un objet de la classe complexpossède :
• deux attributs : imaget real;
• plusieurs méthodes, comme conjugate(), abs(). . .
La plupart des classes encapsulent à la fois les données et les méthodes applicables aux
objets. Par exemple un objet strcontient une chaîne de caractères Unicode (les données) et de
nombreuses méthodes.
On peut définir un objet comme une capsule contenant des attributs et des méthodes :
, ,
objet = attributs + méthodes
z r
48 La Programmation Orientée Objet
Cette instruction permet d’introduire la définition d’une nouvelle classe (c’est-à-dire d’un
nouveau type de données).
Syntaxe
B class est une instruction composée. Elle comprend un en-tête (avec docstring) + corps indenté
:
>>> class C :
... """Documentation de la clesse C."""
... x = 23
Dans cet exemple, C est le nom de la classe (qui commence conventionnellement par une
majuscule), et xest un a ribut de classe, local à C.
Remarque
✓ En Python (car c’est un langage dynamique comme Ruby, contrairement à C++ ou Java) il
est possible d’ajouter de nouveaux attributs d’instance (ici le a.y = 44) ou même de nouveaux
attributs de classe (ici
C.z = 6).
Définition
Une variable définie au niveau d’une classe (comme x dans la classe C) est appelé attribut de
classe et est partagée par tous les objets instances de cette classe.
Définition
Une variable définie au niveau d’un objet (comme y dans l’objet a) est appelée attribut d’instance
et est liée uniquement à l’objet pour lequel elle est définie.
• les classes peuvent utiliser les variables définies au niveau principal mais elles ne peuvent
pas les modifier ;
• les instances peuvent utiliser les variables définies au niveau de la classe mais elles ne
peuvent pas les modifier (pour cela elles sont obligées de passer par l’espace de noms de
la classe, par exemple
C.x = 3).
Re er e des noms
• Noms non qualifiés (exemple dimension) l’affectation crée ou change le nom dans la portée
locale courante. Ils sont cherchés suivant la règle LGI.
• Noms qualifiés (exemple [Link]) l’affectation crée ou modifie l’attribut dans l’espace
de noms de l’objet. Un attribut est cherché dans l’objet, puis dans toutes les classes dont
l’objet dépend (mais pas dans les modules).
L’exemple suivant affiche le dictionnaire lié à la classe C puis la liste des attributs liés à une
instance de C:
>>> v = 5
>>> class C :
... x = v + 3 # utilisation d'une variable globale dans la définition de classe
... y = x + 1 # recherche dans l'espace de noms de la classe lors de la définition
...
>>> a = C()
>>> a.x # utilisation sans modification de la variable de classe en passant par l'objet
8
>>> a.x = 2 # création d'une variable d'instance pour l'objet a
>>> a.x
2
>>> C.x # la variable de classe n'est pas modifiée
8
>>> C.x = -1 # on modifie la variable de classe en passant par l'espace de noms de la classe
>>> C.x
-1
>>> class C :
... x = 20
...
>>> C. dict
{'x' : 20, ' module ' : ' main ', ' doc ' : None}
>>> a = C()
>>> dir(a)
[' doc ', ' module ', 'x']
7.3 Méthodes
Syntaxe
Une méthode s’écrit comme une fonction du corps de la classe avec un premier paramètre self
obli- gatoire, où selfreprésente l’objet sur lequel la méthode sera appliquée.
Autrement dit self est la référence d’instance.
Syntaxe
B Ces méthodes portent des noms pré-définis, précédés et suivis de deux caractères de
soulignement.
Elles servent :
• à initialiser l’objet instancié ;
• à modifier son affichage ;
• à surcharger ses opérateurs ;
• ...
7.4.1 L’initialisateur
Lors de l’instanciation d’un objet, la structure de base de l’objet est créée en mémoire, et la
méthode
init est automatiquement appelée pour initialiser l’objet. C’est typiquement dans cette méthode
spé- ciale que sont créés les attributs d’instance avec leur valeur initiale.
>>> class C :
... def init (self, n) :
... self.x = n # initialisation de l'attribut d'instance x
...
>>> une_instance = C(42) # paramètre obligatoire, affecté à n
>>> une_instance.x
42
x = 7 + 9 # addition entière
s = 'ab' + 'cd' # concaténation
Définition
Le polymorphisme par dérivation est la faculté pour deux méthodes (ou plus) portant le même nom
1. Pour plus de détails, consulter la documentation de référence du langage Python ( e Python language reference) section
3,
Data model, sous-section 3.3, Special method names.
2. Rappelons qu’il existe deux façons d’afficher un résultat : repr() et str(). La première est « pour la machine », la seconde
« pour l’utilisateur ».
52 La Programmation Orientée Objet
mais appartenant à des classes héritées distinctes d’effectuer un travail différent. Cette
propriété est ac- quise par la technique de la surcharge.
Bien sûr, ces deux conceptions peuvent cohabiter, et c’est souvent le cas !
7.6.1 Association
Définition
b Une association représente un lien unissant les instances de classe. Elle repose sur la relation
« a-un » ou « utilise-un ».
class Point :
def init (self, x, y) :
[Link], [Link] = x, y
class Segment :
"""Classe conteneur utilisant la classe Point."""
def init (self, x1, y1, x2, y2) :
[Link] = Point(x1, y1)
[Link] = Point(x2, y2)
.format([Link], [Link],
[Link], [Link]))
Agrégation
Définition
b Une agrégation est une association non symétrique entre deux classes (l’agrégat et le composant).
Composition
Définition
b Une composition est un type particulier d’agrégation dans laquelle la vie des composants
est liée à celle de l’agrégat.
7.6.2 Dérivation
Définition
b La dérivation décrit la création de sous-classes par spécialisation. Elle repose sur la relation « est-un
».
class Atome :
"""atomes simplifiés (les 10 premiers éléments)."""
def affiche(self) :
print()
print("Nom de l'élément :", [Link][[Link]][0])
print("%s protons, %s électrons, %s neutrons" % ([Link], [Link], [Link]))
"""
La POO graphique
Très utilisée dans les systèmes d’exploitation et dans les applications, les interfaces graphiques
sont programmables en Python.
import tkinter
Définition
b On appelle widget (mot valise, contraction de window et gadget) les composants graphiques
de base d’une bibliothèque.
Liste des principaux widgets de tkinter :
Tk fenêtre de plus haut niveau
Frame contenant pour organiser d’autres widgets
Label zone de message
Button bouton d’action avec texte ou
image Message zone d’affichage multi-
lignes Entry zone de saisie
Che button bouton à deux états
Radiobutton bouton à deux états exclusifs par groupe de boutons
Scale glissière à plusieurs positions
PhotoImage sert à placer des images (GIF et PPM/PGM) sur des
widgets BitmapImage sert à placer des bitmaps (X11 bitmap data) sur
des widgets Menu menu déroulant associé à un Menubutton
Menubutton bouton ouvrant un menu d’options
Scrollbar ascenseur
Listbox liste à sélection pour des textes
Text édition de texte simple ou multi-lignes
Canvas zone de dessins graphiques ou de photos
1. Langage développé en 1988 par John K. O. de l’Université de Berkeley.
8.3 Deux exemples 59
Notion de callba
Nous avons vu que la programmation d’interface graphique passe par une boucle principale
chargée de traiter les différents évènements qui se produisent.
Cette boucle est généralement gérée directement par la bibliothèque d’interface graphique
utilisée, il faut donc pouvoir spécifier à cette bibliothèque quelles fonctions doivent être
appelées dans quels cas. Ces fonctions sont nommées des callbacks — ou rappels — car
elles sont appelées directement par la bibliothèque d’interface graphique lorsque des
évènements spécifiques se produisent.
Conception graphique
La conception graphique va nous aider à choisir les bons widgets.
En premier lieu, il est prudent de commencer par une conception manuelle ! En effet rien ne
vaut un papier, un crayon et une gomme pour se faire une idée de l’aspect que l’on veut obtenir.
Chacune de ces zones est codée par une instance de Frame(), positionnée l’une sous l’autre grâce
au
packer, et toutes trois incluses dans une instance de Tk()(cf. conception ☞ Fig. 8.3).
Voici donc dans un premier temps le code de l’interface graphique. L’initialisateur crée l’attribut
phoneList,une liste qu’il remplit avec le contenu du fichier contenant les données (si le fichier
n’existe pas il est créé), crée la fenêtre de base rootet appelle la méthode makeWidgets().
60 La POO graphique
Cette méthode, suit la conception graphique exposée ci-dessus et remplit chacun des trois frames.
8.3 Deux exemples 61
Comme tout bon module, un auto-test permet de vérifier le bon fonctionnement (ici le bon
aspect) de l’interface :
# -*- coding : utf-8 -*-
# Bob Cordeau
# tkPhone_IHM.py
import tkinter as tk
from [Link] import isfile
# class
class Allo_IHM :
"""IHM de l'application 'répertoire téléphonique'."""
def init (self, fic) :
"""Initialisateur/lanceur de la fenêtre de base"""
[Link] = []
[Link] = fic
if isfile([Link]) :
with open([Link]) as f :
for line in f :
[Link](line[:-1].split('*'))
else :
with open([Link], "w", encoding="utf8") :
pass
[Link]()
[Link] = [Link]()
[Link]("Allo !")
[Link](relief=[Link], bd=3)
[Link]()
[Link]()
[Link]()
def makeWidgets(self) :
"Configure et positionne les widgets"
62 La POO graphique
[Link] = [Link](frameM)
[Link] = [Link](frameM, yscrollcommand=[Link], height=6)
[Link](command=[Link])
[Link](side=[Link], fill=tk.Y, pady=5)
[Link](side=[Link], fill=[Link], expand=1, pady=5)
## remplissage de la Listbox
for i in [Link] :
[Link]([Link], i[0])
[Link]("<Double-Button-1>", lambda event : [Link](event))
def ajouter(self) :
pass
def supprimer(self) :
pass
def clear(self) :
pass
# auto-test
if name == ' main ' :
# instancie l'IHM, callbacks inactifs
app = Allo_IHM("./[Link]")
Le code de l’application
On va maintenant utiliser le module de la façon suivante :
– On importe la classe Allo_IHM depuis le module précédent ;
– on crée une classe Allo qui en dérive ;
– son initialisateur appelle l’initialisateur de la classe de base pour hériter de toutes ses
caractéris- tiques ;
– il reste à surcharger les
callbacks. Enfin, le script instancie
l’application.
8.3 Deux exemples 63
# Bob Cordeau
# [Link]
# import
from tkPhone_IHM import Allo_IHM
# définition de classe
class Allo(Allo_IHM) :
"""Repertoire téléphonique."""
def ajouter(self) :
# maj de la liste
ajout = ["", ""]
ajout[0] = [Link]()
ajout[1] = [Link]()
if (ajout[0] == "") or (ajout[1] == "") :
return
[Link](ajout)
[Link]()
# maj de la listebox
[Link](0, 'end')
for i in [Link] :
[Link]('end', i[0])
[Link]()
[Link]()
# maj du fichier
f = open([Link], "a")
[Link]("%s*%s\n" % (ajout[0], ajout[1]))
[Link]()
def supprimer(self) :
[Link]()
# maj de la liste
retrait = ["", ""]
retrait[0], retrait[1] = [Link][int([Link]()[0])]
[Link](retrait)
# maj de la listebox
[Link](0, 'end')
for i in [Link] :
[Link]('end', i[0])
# maj du fichier
f = open([Link], "w")
for i in [Link] :
[Link]("%s*%s\n" % (i[0], i[1]))
[Link]()
def clear(self) :
[Link](0, 'end')
[Link](0, 'end')
La fonction help()
If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http ://[Link]/tutorial/.
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
help> []
no Python documentation found for '[]'
help> quit
You are now leaving help and returning to the Python interpreter.
If you want to ask for help on a particular object directly from the
interpreter, you can type "help(object)". Executing "help('string')"
has the same effect as typing a particular string at the help> prompt.
>>>
66 Techniques avancées
class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable`s items
| add (...)
| x. add (y) <==> x+y
| (...)
| x. (y) <==> y in x
...
| reverse(...)
| [Link]() -- reverse *IN PLACE*
| sort(...)
| [Link](cmp=None, key=None, reverse=False) -- stable sort *IN PLACE* ;
| cmp(x, y) -> -1, 0, 1
|
| Data and other attributes defined here :
| hash = None
affiche la documentation :
[Link](object) -- append object to end
[Link](value) -> integer -- return number of occurrences of value
[Link](iterable) -- extend list by appending elements from the iterable
[Link](value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
[Link](index, object) -- insert object before index
[Link]([index]) -> item -- remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
[Link](value) -- remove first occurrence of value.
Raises ValueError if the value is not present.
[Link]() -- reverse *IN PLACE*
[Link](cmp=None, key=None, reverse=False) -- stable sort *IN PLACE* ;
cmp(x, y) -> -1, 0, 1
Elle fournissent respectivement le type, les méthodes et la localisation mémoire (unique) d’un
objet :
>>> li = [1, 2, 3]
>>>
>>> type(li)
9.1 Techniques procédurales 67
<class 'list'>
>>>
>>> dir(li)
[' add ', ' class ', ' contains ', ' delattr ', ' delitem ', ' doc ', ' eq ', ' format ', ' ge ', '
getattribute ', ' getitem ', ' gt ', ' hash ', ' iadd ', ' imul ', ' init ', ' iter ', ' le
', ' len ', ' lt ', ' mul ', ' ne ', ' new ', ' reduce ', ' reduce_ex ', ' repr ', ' reversed
', ' rmul ', ' setattr ', ' setitem ', ' sizeof ', ' str ', ' subclasshook ', 'append', 'count', '
extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>>
>>> id(li)
3074801164
Comme nos l’avons vu au chapitre 5.3.1, p. 37, ces fonctions retournent respectivement le
dictionnaire des noms locaux (globaux) au moment de leur appel.
Le module sys
L’interpréteur IPython
Cet interpréteur qui vient récemment de passer en version 1.0 est certainement le meilleurs outil
disponible, spécialement dans les domaines de la documentation et de l’introspection.
Ipython est également très utile pour la recherche des erreurs de programmation (bugs).
68 Techniques avancées
# au lieu de ce code :
try :
fh = open(filename)
for line in fh :
process(line)
finally :
[Link]()
animaux = []
nombre_de_felins = 0
def gererChat() :
global nombre_de_felins
print("Miaou")
[Link]("félin")
nombre_de_felins += 1
def gererChien() :
print("Ouah")
[Link]("canidé")
def gererOurs() :
print("Attention au *OUILLE* !")
[Link]("plantigrade")
# =============================================================================
dico = {
"chat" : gererChat,
"chien" : gererChien,
"ours" : gererOurs
nf = nombre_de_felins
print("nous avons rencontré {} félin(s)".format(nf))
print("Les animaux rencontrés sont : {}".format(', '.join(animaux), end=" ")
"""
Miaou
Attention au *OUILLE* !
Miaou
Ouah
nous avons rencontré 2 félin(s)
Les animaux rencontrés sont : félin, plantigrade, félin, canidé
"""
9.1 Techniques procédurales 69
def listeFichiersPython(repertoire) :
"""Affiche récursivement les fichiers Python à partir de <repertoire>."""
noms = listdir(repertoire)
for nom in noms :
if nom in (".", "..") :
continue
nom_complet = join(repertoire, nom)
if isdir(nom_complet) :
listeFichiersPython(nom_complet)
elif [Link](".py") or [Link](".pyw") :
print("Fichier Python :", nom_complet)
listeFichiersPython("/home/bob/Tmp")
Dans cette définition, on commence par constituer dans la variable noms la liste des fichiers et
réper- toires du répertoire donné en paramètre. Puis, dans une boucle for, tant que l’élément
examiné est un répertoire, on ré-appelle la fonction sur lui pour descendre dans l’arborescence
de fichiers tant que la condition terminale (if nom in (".", ".."):) est fausse.
Le résultat produit est :
Fichier Python : /home/bob/Tmp/parfait_chanceux.py
Fichier Python : /home/bob/Tmp/[Link]
Fichier Python : /home/bob/Tmp/parfait_chanceux_m.py
Fichier Python : /home/bob/Tmp/verif_m.py
Fichier Python : /home/bob/Tmp/Truc/Machin/tkPhone_IHM.py
Fichier Python : /home/bob/Tmp/Truc/Machin/[Link]
Fichier Python : /home/bob/Tmp/Truc/[Link]
Fichier Python : /home/bob/Tmp/Truc/tk_variable.py
{x2 |x ∈ [2, 11[} ⇔ [x**2 for x in range(2, 11)]⇒ [4, 9, 16, 25, 36, 49, 64, 81, 100]
Définition
Une liste en compréhension est équivalente à une boucle forqui construirait la même liste en
utilisant
la méthode append().
Autre exemple :
>>> C_deg = range(-20, 41, 5)
>>> F_deg = [(9.0/5)*c + 32 for c in C_deg]
>>> table = [C_deg, F_deg]
>>> for i in range(len(table[0])) :
... print(table[0][i], "=>", table[1][i])
...
-20 => -4.0
-15 => 5.0
-10 => 14.0
-5 => 23.0
0 => 32.0
5 => 41.0
10 => 50.0
15 => 59.0
20 => 68.0
25 => 77.0
30 => 86.0
35 => 95.0
40 => 104.0
Les générateurs fournissent un moyen de générer des exécutions paresseuses, ce qui signifie
qu’elles ne calculent que les valeurs réellement demandées. Ceci peut s’avérer beaucoup plus
efficace (en termes de mémoire) que le calcul, par exemple, d’une énorme liste en une seule fois.
Ce qui produit :
0 1 2 3 4 5
Utilisation
Les expressions génératrices (souvent appelée « genexp ») sont aux générateurs ce que les
listes en com- préhension sont aux fonctions. Bien qu’il soit transparent, le mécanisme du yield vu
ci-dessus est encore en action.
Par exemple l’expression suivante génère la création d’un million de valeurs en mémoire avant
de commencer la boucle :
for i in [x**2 for x in range(1000000)]:
Voici un autre exemple : une genexp de recherche d’un motif dans un fichier, analogue à un
grep
simplifié 1 :
1. Célèbre utilitaire Unix.
72 Techniques avancées
Syntaxe
Soit deco() un décorateur. Pour « décorer » une fonction on écrit :
9.2 Techniques objets 73
def deco() :
...
@deco
def fonction(arg1, arg2, ...) :
pass
def f2() :
...
def f3() :
...
return _interne
@unDecorateur
def uneFonction(a, b) :
return a + b
def autreFonction(a, b) :
return a + b
print(uneFonction(3, 4))
print(autreFonction(6, 7))
"""
Fonction decorée : uneFonction. Appel numéro 1
3
Fonction decorée : autreFonction. Appel numéro 1
3
Fonction decorée : uneFonction. Appel numéro 2
7
Fonction decorée : autreFonction. Appel numéro 2
13
"""
Il est possible de transformer les instances d’une classe en functor si la méthode spéciale
call ()est définie dans la la classe :
>>> class A :
... def init (self) :
... [Link] = []
... def call (self, a, b) :
... [Link]((a, b))
... return a + b
...
>>> a = A()
>>> a(1, 2)
>>> a(3, 4)
>>> a(5, 6)
11
>>> [Link]
[(1, 2), (3, 4), (5, 6)]
Python propose un mécanisme 4 pour émuler les attribut privés : les identificateurs de la classe
com- mencent par deux soulignés. Par exemple ident. Mais cette protection reste déclarative
et n’offre pas une sécurité absolue.
1. callable en anglais.
2. Cette notion sera développée section 9.3.1, p. 78.
3. Slogan des développeurs Python : « We’re all consenting adults here » (nous sommes entre adultes consentants).
4. le name mangling.
9.2 Techniques objets 75
La solution property
class C :
def init (self) :
self._ma_propriete = None
def getx(self) :
"""getter."""
return self._x
def delx(self) :
"""deleter."""
del self._x
# auto-test =========================================================
if name == ' main ' :
test = C()
test.x = 10 # setter
print(test.x) # getter
"""
10
Je suis la propriété 'x'.
"""
documentation) :
La seconde, plus simple, utilise la syntaxe des décorateurs. On remarque que la chaîne de
documenta- tion de la property est ici la docstring de la définition de la propriété x:
# !/usr/bin/python3
#-*- coding : utf-8 -*-
# fichier : [Link]
class C :
def init (self) :
self._x = None
@property
def x(self) :
"""Je suis la propriété 'x'."""
return self._x
@[Link]
def x(self, value) :
self._x = value
@[Link]
def x(self) :
76 Techniques avancées
del self._x
# auto-test =========================================================
if name == ' main ' :
test = C()
test.x = 10 # setter
print(test.x) # getter
"""
10
Je suis la propriété 'x'.
"""
Schéma de conception : nous allons tout d’abord définir une classe Point que nous utiliserons
comme classe de base de la classe Cercle.
@property
def distance_origine(self) :
return [Link](self.x, self.y)
De nouveau, les méthodes renvoyant un simple flottant seront utilisées comme des attributs
grâce à
property :
9.2 Techniques objets 77
class Cercle(Point) :
def init (self, rayon, x=0, y=0) :
super(). init (x, y)
[Link] = rayon
@property
def aire(self) : return [Link] * ([Link] ** 2)
@property
def circonference(self) : return 2 * [Link] * [Link]
@property
def distance_bord_origine(self) :
return abs(self.distance_origine - [Link])
@[Link]
def rayon(self, rayon) :
assert rayon > 0, "rayon strictement positif"
self. rayon = rayon
Autre exemple :
class Duck :
def quack(self) :
print("Quaaaaaack !")
def feathers(self) :
print("The duck has white and gray feathers.")
class Person :
def quack(self) :
print("The person imitates a duck.")
def feathers(self) :
print("The person takes a feather from the ground and shows it.")
78 Techniques avancées
def in_the_forest(duck) :
[Link]()
[Link]()
def game() :
donald = Duck()
john = Person()
in_the_forest(donald)
in_the_forest(john)
"""
Quaaaaaack !
The duck has white and gray feathers.
The person imitates a duck.
The person takes a feather from the ground and shows it.
"""
Issue de langages fonctionnels (comme Lisp), la directive lambdapermet de définir un objet fonction
anonyme dont le bloc d’instructions est limité à une expression dont l’évaluation fournit la valeur
de retour de la fonction.
Syntaxe
lambda [parameters] :expression
Par exemple cette fonction retourne « s » si son argument est différent de 1, une chaîne vide
>>> s = lambda x : "" if x == 1 else "s"
>>>
>>> s(3)
's'
>>> s(1)
''
sinon :
La fonction map() :
map() applique une fonction à chaque élément d’une séquence et retourne un itérateur :
1. cf. Wikipedia
9.3 Techniques fonctionnelles 79
La fonction filter() :
filter() construit et renvoie un itérateur sur une liste qui contient tous les éléments de la
séquence initiale répondant au critère :
function(element) == True :
>>> list(filter(lambda x : x > 4, range(10)))
[5, 6, 7, 8, 9]
La fonction reduce() :
reduce() est une fonction du module functools. Elle applique de façon cumulative une fonction de
deux arguments aux éléments d’une séquence, de gauche à droite, de façon à réduire cette
séquence à une seule valeur qu’elle renvoie :
>>> def somme(x, y) :
... print x, '+', y
... return x + y
...
>>> reduce(somme, [1, 2, 3, 4])
1 + 2
3 + 3
6 + 4
10
>>>
>>> sum([1, 2, 3, 4])
10
On remarque que reduce() peut être remplacée par une des fonctions suivantes : all(), any(), max(),
min()ou sum().
Elles sont aussi utiles pour fournir des modèles partiels de widgets, qui ont souvent de
nombreux paramètres. Dans l’exemple suivant, on redéfinit la classe Button en fixant certains de
ses attributs (qui peuvent toujours être surchargés) :
80 Techniques avancées
root = [Link]()
# instanciation partielle de classe :
MonBouton = partial([Link], root, fg='purple', bg='green')
MonBouton(text="Bouton 1").pack()
MonBouton(text="Bouton 2").pack()
MonBouton(text="QUITTER", bg='red', fg='black',
command=[Link]).pack(fill=tk.X, expand=True)
[Link]("PFA !")
[Link]()
Le module pickle
L’intérêt du module pickleest sa simplicité. Par contre, ce n’est pas un format répendu : il n’est utile
que tant que l’on reste dans le monde Python.
On peut utiliser une chaîne pour sérialiser, mais l’usage le plus commun est d’utiliser un
fichier. Par exemple pour un dictionnaire :
import pickle
Le module json
Le module jsonpermet d’encoder et de décoder des informations au format JSON1. C’est un format
d’échange très utile, implémenté dans un grand nombre de langages, plus lisible que XMLmais
moins puissant.
On utilise la même syntaxe qu’avec pickle, à savoir dumps() et loads() pour une chaîne, dump() et
load() pour un fichier :
import json
# décodage
with open("json_tst") as f :
print([Link](f))
Le fichier tel_bd produit peut être visualisé par le programme SQLite database browser :
Dans cette introduction, nous nous limiterons à une courte présentation des tests
unitaires.
Le module Python unittest fournit l’outil PyUnit, outil que l’on retrouve dans d’autres langages : JUnit
(Java), NUnit (.Net), JSUnit (Javascript), tous dérivés d’un outil initialement développé pour le
langage SmallTalk : SUnit.
PyUnit propose une classe de base, TestCase. Chaque méthode implémentée dans une
classe dérivée de TestCase, et préfixée de test_, sera considérée comme un test unitaire 2 :
"""Module de calculs."""
# fonctions
def moyenne(*args) :
"""Renvoie la moyenne."""
length = len (args)
sum = 0
for arg in args :
sum += arg
return sum/length
def division(a, b) :
"""Renvoie la division."""
return a/b
# import
import sys
import unittest
from [Link] import abspath, dirname
def test_moyenne(self) :
[Link](moyenne(1, 2, 3), 2)
1. Cf. la loi de M .
2. cf. [7], p. 123.
9.6 La documentation des sources 83
[Link](moyenne(2, 4, 6), 4)
def test_division(self) :
[Link](division(10, 5), 2)
[Link](ZeroDivisionError, division, 10, 0)
def test_suite() :
tests = [[Link](CalculTest)]
return [Link](tests)
# auto-test ===================================================================
if name == ' main ' :
[Link]()
"""
..
OK
"""
docutils
Le projet docutils, qui inclut l’interpréteur reST, fournit un jeu d’utilitaires :
rst2html génère un rendu html avec une feuille de style css intégrée ;
rst2latex crée un fichier LATEX équivalent ;
rst2s5 construit une présentation au format s5, qui permet de créer des présentations interactives
en
HTML.
Sphinx
Sphinx est un logiciel libre de type générateur de documentation. Il s’appuie sur des fichiers au
format reStructuredText, qu’il convertit en HTML, PDF, man, et autres formats.
De nombreux projets utilisent Sphinx pour leur documentation officielle, tels que Python, Django,
Selenium, Urwid, ou encore Bazaar.
84 Techniques avancées
rst2pdf
Par ailleurs, le programme rst2pdf génère directement une documentation au format
PDF. Voici un exemple 1 simple de fichier texte au format reST.
On remarque entre autres que :
• la principale balise est la ligne blan e qui sépare les différentes structures du texte ;
• la structuration se fait en soulignant les titres des sections de différents niveaux avec des
caractères de ponctuation (= - _ : , etc.). À chaque fois qu’il rencontre un texte ainsi souligné,
l’interpréteur associe le caractère utilisé à un niveau de section ;
• un titre est généralement souligné et surligné avec le même caractère, comme dans
l’exemple suiv- ant :
======================
Fichier au format reST
======================
Section 1
=========
Sous-section
::::::::::::
Sous-sous-section
.................
.. et ceci un commentaire
Section 2
=========
Section 3
=========
.. figure :: [Link]
:scale : 50%
L’utilitaire rst2pdf, appliqué à ce fichier, produit le fichier de même nom (☞ Fig. 9.6) mais avec
l’ex- tension .pdf.
Pour chacun, nous donnerons d’une part le source muni de sa chaîne de documentation dans
lequel le module standard doctest permet d’extraire puis de lancer ces sessions pour vérifier
qu’elles fonctionnent et, d’autre part un résultat de l’exécution.
import doctest
def somme(a, b) :
"""Renvoie a + b.
>>> somme(2, 2)
>>> somme(2, 4)
6
"""
return a+b
Mode détaillé
Trying :
somme(2, 2)
Expecting :
ok
Trying :
somme(2, 4)
Expecting :
ok
1 items had no tests :
main
items passed all tests :
2 tests in main .somme
tests in 2 items.
2 passed and 0 failed.
Test passed.
# fonctions
def accentEtrange(texte) :
"""Ajoute un accent étrange à un texte.
Exemple :
>>> texte = "Est-ce que tu as regardé la télé hier soir ? Il y avait un théma sur les ramasseurs d'escargots en
Laponie, ils en bavent..."
>>> accentEtrange(texte)
86 Techniques avancées
Est-ceu queu tu as rRreugarRrdé la télé hieurRr soirRr ? Il y avait un théma surRr leus rRramasseuurRrs d'
euscarRrgots eun Laponieu, ils eun baveunt...
def _test() :
import doctest
[Link](verbose=True)
Exemple : test_documentation2.py
Fichier de documentation 1 :
Le module ``accent``
====================
Les ``r`` sont triplés et les ``e`` épaulés par des ``u``. Cette technique permet
de se passer de systèmes de traductions complexes pour faire fonctionner
les logiciels dans certaines régions.
Source du module :
import doctest
[Link]("test_documentation2.txt", verbose=True)
Prérequis
Au fur et à mesure que l’on acquière de l’expérience, on découvre et on apprend à utiliser les
bibliothèques de modules et paquets qui fournissent des types de données et des services
avancés, évitant d’avoir à re- créer, coder et déboguer une partie de la solution.
Réutiliser
La première chose à faire est de vérifier qu’il n’existe pas déjà une solution (même partielle) au
problème que l’on pourrait reprendre in extenso ou dont on pourrait s’inspirer. On peut chercher
dans les nombreux modules standard installés avec le langage, dans les dépôts institutionnels
de modules tiers (le Python Package Index 1 par exemple), ou encore utiliser les moteurs de
recherche sur l’Internet. Si on ne trouve pas de solution existante dans notre langage préféré, on
peut trouver une solution dans un autre langage, qu’il n’y aura plus qu’à adapter.
L’analyse qui permet de créer un algorithme et la programmation ensuite, sont deux
phases qui né- cessitent de la pratique avant de devenir « évidentes » ou « faciles ».
Réfléchir à un algorithme
Pour démarrer, il faut partir d’éléments réels, mais sur un échantillon du problème comportant
peu de données, un cas que l’on est capable de traiter « à la main ».
Il est fortement conseillé de démarrer sur papier ou sur un tableau (le papier ayant l’avantage
de laisser plus facilement des traces des différentes étapes).
On identifie tout d’abord quelles sont les données que l’on a à traiter en entrée et quelles
sont les données que l’on s’attend à trouver en sortie. Pour chaque donnée, on essaie de
préciser quel est son domaine, quelles sont ses limites, quelles contraintes la lient aux autres
données.
Résoudre « à la main »
On commence par une résolution du problème, en réalisant les transformations et calculs sur
notre échan- tillon de problème, en fonctionnant par étapes.
À chaque étape, on note :
• quelles sont les étapes pertinentes, sur quels critères elles ont été choisies ;
• quelles sont les séquences d’opérations que l’on a répété.
Lorsque l’on tombe sur des étapes complexes, on découpe en sous-étapes, éventuellement
en les trai- tant séparément comme un algorithme de résolution d’un sous-problème. Le but est
d’arriver à un niveau de détails suffisamment simple ; soit qu’il s’agisse d’opérations très basiques
(opération sur un texte, ex- pression de calcul numérique…), soit que l’on pense/sache qu’il existe
déjà un outil pour traiter ce sous- problème (calcul de sinus pour un angle, opération de tri sur
une séquence de données. . .).
Lors de ce découpage, il faut éviter de considérer des opérations comme « implicites » ou «
évidentes », il faut préciser d’où proviennent les informations et ce que l’on fait des résultats.
Par exemple on ne
1. [Link]
96 Passer du problème au
programme
considère pas « un élément » mais « le nom traité est l’élément suivant de la séquence de noms
» ou encore « le nom traité est le xe élément de la séquence de noms ».
Normalement, au cours de ces opérations, on a commencé à nommer les données et les
étapes au fur et à mesure qu’on en a eu besoins.
Formaliser
Une fois qu’on a un brouillon des étapes, il faut commencer à mettre en forme et à identifier les
construc- tions algorithmiques connues et les données manipulées :
Factoriser
Le but est d’identifier les séquences d’étapes qui se répètent en différents endroits, séquences
qui seront de bons candidats pour devenir des fonctions ou des classes. Ceci peut être fait en
même temps que l’on formalise.
• Les noms des choses que l’on a manipulé vont nous donner des variables.
• Les tests vont se transformer en if condition:
• Les boucles sur des séquences d’informations vont se transformer en for variable in séquence:
• Les boucles avec expression de condition vont se transformer en while conditions:
• Les séquences d’instructions qui se répètent en différents endroits vont se transformer en
fonc-tions.
• Le retour de résultat d’une séquence (fonction) va se traduire en return variable.
• Les conditions sur les données nécessaires pour un traitement vont identifier des tests
d’erreurs et des levées d’exception.
A C
Position du problème
Nous avons vu que l’ordinateur code toutes les informations qu’il manipule en binaire. Pour coder
les nombres entiers un changement de base suffit, pour les flottants, on utilise une norme (IEEE
754), mais la situation est plus complexe pour représenter les caractères.
En effet, la grande diversité des langues humaines et de leur représentation nécessite un codage
adapté.
La première idée est de construire une table qui associe les symboles à représenter à
un nombre (généralement codé sur un octet) :
Symbole ←→ Nombre
La plus célèbre est la table ASCII 1 (☞ Fig. C.1), codée sur 7 bits (soit 128 codes), mais bien
d’autres tables ont été créées (EBCDIC, ISO-8852-1. . .).
La table Unicode
En Python 3, les chaînes de caractères (le type str()) sont des chaînes Unicode, norme dans
laquelle les identifiants numériques de leurs caractères sont uniques et universels.
Comme il s’agit de différencier plusieurs centaines de milliers de caractères (on compte
environ 6000 langues dans le monde) ils ne pourront évidemment pas être encodés sur un seul
octet.
En fait, la norme Unicode ne fixe aucune règle concernant le nombre d’octets ou de bits à
réserver pour l’encodage, mais spécifie seulement la valeur numérique de l’identifiant associé à
chaque caractère (☞ Fig. C.2).
1. American Standard Code for Information Interchange
98 Jeux de caractères et
encodage
Encodage
Après avoir collecté tous les symboles et y avoir associé un nombre, il reste à leur trouver une
représenta- tion binaire.
Pour l’ASCII un seul octet suffisait mais pour représenter les millions de possibilités de
l’Unicode, plusieurs octets par caractère sont nécessaires.
Comme la plupart des textes n’utilisent que la table ASCII ce qui correspond justement à
la partie basse de la table Unicode, l’encodage le plus économique est l’UTF-8 1 :
• pour les codes 0 à 127, l’UTF-8 utilise l’octet de la table ASCII ;
• pour les caractères spéciaux (codes 128 à 2047), l’UTF-8 utilise 2 octets ;
• pour les caractères spéciaux encore moins courants (codes 2048 à 65535), l’UTF-8 utilise 3
octets ;
• enfin pour les autres, l’UTF-8 en utilise 4.
ou :
# -*- coding : utf8 -*-
1. Retour chap. 2, p. 5
2. appelé codec.
3. Notons que latin1et utf8sont des alias de latin-1et utf-8.
ANNEXE D
Définition
Définition
En arithmétique, une base n désigne la valeur dont les puissances successives interviennent
dans l’écriture des nombres, ces puissances définissant l’ordre de grandeur de chacune des
positions occupées par les chiffres composant tout nombre. Par exemple : 57n = (5 × n1) + (7
× n0)
Certaines bases sont couramment employées :
• la base 2 (système binaire), en électronique numérique et informatique ;
• la base 8 (système octal), en informatique ;
• la base 16 (système hexadécimal), fréquente en informatique ;
• la base 60 (système sexagésimal), dans la mesure du temps et des angles.
Conversion
Définition
Les changements de base : un nombre dans une base n donnée s’écrit sous la forme d’addition des
puissances successives de cette base 1.
Exemples
1. Retour chap.2, p. 7
Annexe E
Exercices corrigés
1. Écrire un programme qui, à partir de la saisie d’un rayon et d’une hauteur, calcule le
volume d’un cône droit.
2. Une boucle while : entrez un prix HT (entrez 0 pour terminer) et affichez sa valeur TTC.
3. Une autre boucle while : calculez la somme d’une suite de nombres positifs ou nuls.
Comptez com- bien il y avait de données et combien étaient supérieures à 100.
Entrer un nombre inférieur ou égal à 0 indique la fin de la suite.
4. L’utilisateur donne un entier positif n et le programme affiche PAIR s’il est divisible par 2, IMPAIR
sinon.
7. Écrire un programme qui approxime par défaut la valeur de la constante mathématique e, pour
n
assez grand 1, en utilisant la formule :
∑ n1
e ≈
i!
i=0
Pour cela, définissez la fonction factorielle et, dans votre programme principal, saisissez
l’ordre n et affichez l’approximation correspondante de e.
8. Un gardien de phare va aux toilettes cinq fois par jour or les WC sont au rez-de-chaussée.. .
Écrire une procédure (donc sans return) hauteurParcourue qui reçoit deux paramètres, le
nombre de marches du phare et la hauteur de chaque marche (en cm), et qui affiche :
Pour x marches de y cm, il parcourt [Link] m par semaine.
On n’oubliera pas :
• qu’une semaine comporte 7 jours ;
• qu’une fois en bas, le gardien doit remonter ;
• que le résultat est à exprimer en m.
1. Mais pas trop pour éviter le dépassement de capacité : OverflowError : long int too large to convert to float.
102 Exercices corrigés
10. Je suis ligoté sur les rails en gare d’Arras. Écrire un programme qui affiche un tableau me
permettant de connaître l’heure à laquelle je serai déchiqueté par le train parti de la gare du
Nord à 9h (il y a 170 km entre la gare du Nord et Arras).
Le tableau prédira les différentes heures possibles pour toutes les vitesses de 100 km/h à
300 km/h, par pas de 10 km/h, les résultats étant arrondis à la minute inférieure.
– Écrire une procédure tchacatchac qui reçoit la vitesse du train et qui affiche l’heure du drame
;
– écrire le programme principal qui affiche le tableau demandé.
✠ 11. Un programme principal saisit une chaîne d’ADN valide et une séquence d’ADN valide («
valide » signifie qu’elles ne sont pas vides et sont formées exclusivement d’une
combinaison arbitraire de
"a", "t", "g" ou "c").
Écrire une fonction validequi renvoie vrai si la saisie est valide, faux sinon.
Écrire une fonction saisiequi effectue une saisie valide et renvoie la valeur saisie sous forme
d’une chaîne de caractères.
Écrire une fonction proportion qui reçoit deux arguments, la chaîne et la séquence et qui
retourne la proportion de séquence dans la chaîne (c’est-à-dire son nombre
d’occurrences).
Le programme principal appelle la fonction saisie pour la chaîne et pour la séquence et
affiche le résultat.
Exemple d’affichage :
chaîne : attgcaatggtggtacatg
séquence : ca
Il y a 10.53 % de "ca" dans votre chaîne.
12. Il s’agit d’écrire, d’une part, un programme principal et, d’autre part, une fonction utilisée
dans le programme principal.
La fonction listAleaInt(n, a, b)retourne une liste de nentiers aléatoires dans [a .. b]en utilisant la
fonction randint(a, b)du module random.
Dans le programme principal :
• construire la liste en appelant la fonction listAleaInt();
• calculer l’index de la case qui contient le minimum ;
• échangez le premier élément du tableau avec son minimum.
13. Comme précédemment, il s’agit d’écrire, d’une part, un programme principal et, d’autre
part, une fonction utilisée dans le programme principal.
La fonction listAleaFloat(n) retourne une liste de n flottants aléatoires en utilisant la fonction
random()du module random.
Dans le programme principal :
• Saisir un entier ndans l’intervalle : [2 .. 100];
• construire la liste en appelant la fonction listAleaFloat();
• afficher l’amplitude du tabeau (écart entre sa plus grande et sa plus petite valeur) ;
• afficher la moyenne du tableau.
15. Saisir un entier entre 1 et 3999 (pourquoi cette limitation ?). L’afficher en nombre romain.
✠ 17. Un tableau contient n entiers (2 < n < 100) aléatoires tous compris entre 0 et 500.
Vérifier qu’ils sont tous différents.
18. Proposer une autre version très simple du problème précédent en comparant les
longueurs des ✠tabeaux avant et après traitement, le traitement consiste à utiliser une
structure de données con- tenant des éléments uniques.
19. L’utilisateur donne un entier n entre 2 et 12, le programme donne le nombre de façons de
faire n en lançant deux dés.
20. Même problème que le précédent mais avec n entre 3 et 18 et trois dés.
21. Généralisation des deux questions précédentes. L’utilisateur saisit deux entrées, d’une part le nom-
✠✠
bre de dés, nbd (que l’on limitera pratiquement à 10) et, d’autre part la somme, s, comprise
entre
nbd et [Link]. Le programme calcule et affiche le nombre de façons de faire s avec les nbd dés.
# import
from sys import exit
# définition de fonction
def verif(entree, reference, precision=0, comment="") :
"""Vérifie que <entree> est égal à <référence>, à la précision près."""
print("{} [{}, {}]".format(comment, entree, reference), end=" ")
if abs(entree - reference) <= precision :
print(" *** ok")
else :
print(" ### ko")
# Auto-test ===================================================================
if name ==' main ' :
verif(abs(-6/2), 3, comment="\nTeste la fonction 'abs' : ")
pi = 3.142
print("\npi = {}".format(pi))
verif(pi, 3.14, 1e-2, comment="à 1e-2 :") # Ok
verif(pi, 3.14, 1e-3, comment="à 1e-3 :") # Erreur
– une boucle de parcours de l’intervalle [2, 1000] incluant les tests nécessaires pour
remplir ces listes ;
– enfin l’affichage de ces listes.
# import
from math import pi
volume = (pi*rayon*rayon*hauteur)/3.0
print("Volume du cône =", volume, "m3")
if n%2 == 0:
print(n, "est pair.")
else :
Exercices corrigés 105
cpt = 0
while n%2 == 0:
n /= 2
cpt += 1
if not cpt :
print("aucun ! Il est premier.")
else :
print("(soit", cpt, "diviseurs propres)")
# définition de fonction
def fact(n) :
r = 1
for i in range(1, n+1) :
r *= i
return r
# définition de fonction
def hauteurParcourue(nb, h) :
print("Pour { :d} marches de { :d} cm, il parcourt { :.2f} m par semaine !"
.format(nb, h, nb*h*2*5*7/100.0))
106 Exercices corrigés
hauteurParcourue(nbMarches, hauteurMarche)
# définition de fonction
def permisSup(p, c, v, a) :
pointsPerdus = p + 3*c + 5*v + 10*a
nbrePermis = pointsPerdus/100.0
return 200*nbrePermis
# définition de fonction
def tchacatchac(v) :
"""Affiche l'heure du drame."""
heure = 9 + int(170/v)
minute = (60 * 170 / v) % 60
print("A { :>3} km/h, je me fais déchiqueter à { :>2} h { :.2f} min."
.format(v, heure, minute))
# définition de fonction
def valide(seq) :
"""Retourne vrai si la séquence est valide, faux sinon."""
ret = any(seq)
for c in seq :
ret = ret and c in "atgc"
return ret
def proportion(a, s) :
"""Retourne la proportion de la séquence <s> dans la chaîne <a>."""
return 100*[Link](s)/len(a)
def saisie(ch) :
s = input("{ :s} : ".format(ch))
while not valide(s) :
print("'{ :s}' ne peut contenir que les chaînons 'a', 't', 'g' et 'c'"
Exercices corrigés 107
# import
from random import seed, randint
# définition de fonction
def listAleaInt(n, a, b) :
"""Retourne une liste de <n> entiers aléatoires dans [<a> .. <b>]."""
return [randint(a, b) for i in range(n)]
# import
from random import seed, random
# définition de fonction
def listAleaFloat(n) :
"Retourne une liste de <n> flottants aléatoires"
return [random() for i in range(n)]
# définition de fonction
def minMaxMoy(liste) :
"""Renvoie le min, le max et la moyenne de la liste."""
min, max, som = liste[0], liste[0], float(liste[0])
for i in liste[1:]:
if i < min :
108 Exercices corrigés
min = i
if i > max :
max = i
som += i
return (min, max, som/len(liste))
if n >= 900:
s += "CM"
n -= 900
if n >= 500:
s += "D"
n -= 500
if n >= 400:
s += "CD"
n -= 400
if n >= 90:
s += "XC"
n -= 90
if n >= 50:
s += "L"
n -= 50
if n >= 40:
s += "XL"
n -= 40
if n >= 9:
s += "IX"
n -= 9
if n >= 5:
s += "V"
n -= 5
if n >= 4:
s += "IV"
n -= 4
while n >= 1:
Exercices corrigés 109
s += "I"
n -= 1
# globales
CODE = zip(
[1000,900 ,500,400 ,100,90 ,50 ,40 ,10 ,9 ,5 ,4 ,1],
["M" ,"CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
# définition de fonction
def decToRoman(num) :
res = []
for d, r in CODE :
while num >= d :
[Link](r)
num -= d
return ''.join(res)
# import
from random import seed, randint
# définition de fonction
def listAleaInt(n, a, b) :
"""Retourne une liste de <n> entiers aléatoires entre <a> et <b>."""
return [randint(a, b) for i in range(n)]
# construction de la liste
seed() # initialise le générateur de nombres aléatoires
t = listAleaInt(n, 0, 500)
# Sont-ils différents ?
tousDiff = True
i = 0
while tousDiff and i < (n-1) :
j = i + 1
while tousDiff and j < n :
if t[i] == t[j]:
tousDiff = False
else :
j += 1
i += 1
if tousDiff :
print("\nTous les éléments sont distincts.")
else :
print("\nAu moins une valeur est répétée.")
print(t)
# import
from random import seed, randint
# définition de fonction
def listAleaInt(n, a, b) :
"""Retourne une liste de <n> entiers aléatoires entre <a> et <b>."""
return [randint(a, b) for i in range(n)]
if len(avant) == len(apres) :
print("\nTous les éléments sont distincts.")
else :
print("\nAu moins une valeur est répétée.")
print(avant)
s = 0
for i in range(1, 7) :
for j in range(1, 7) :
if i+j == n :
s += 1
s = 0
for i in range(1, 7) :
for j in range(1, 7) :
for k in range(1, 7) :
if i+j+k == n :
s += 1
# globale
MAX = 8
if s == nbd or s == 6*nbd :
cpt = 1 # 1 seule solution
else :
I = [1]*nbd # initialise une liste de <nbd> dés
cpt, j = 0, 0
while j < nbd :
som = sum([I[k] for k in range(nbd)])
if som == s :
cpt += 1 # compteur de bonnes solutions
if som == 6*nbd :
break
j = 0
if I[j] < 6:
I[j] += 1
else :
while I[j] == 6:
I[j] = 1
j += 1
I[j] += 1
# globale
MAX = 8
# définition de fonction
def calcul(d, n) :
"""Calcul récursif du nombre de façons de faire <n> avec <d> dés."""
resultat, debut = 0, 1
if (d == 1) or (n == d) or (n == 6*d) : # conditions terminales
return 1
else : # sinon appels récursifs
if n > 6*(d-1) : # optimisation importante
debut = n - 6*(d-1)
for i in range(debut, 7) :
if n == i :
break
resultat += calcul(d-1, n-i)
return resultat
# définition de fonction
def somDiv(n) :
"""Retourne la somme des diviseurs propres de <n>."""
som_div = 1
for div in range(2, (n//2)+1) :
if n % div == 0:
som_div += div
return som_div
def estParfait(n) :
"""Retourne True si <n> est parfait, False sinon."""
return somDiv(n) == n
def estPremier(n) :
"""Retourne True si <n> est premier, False sinon."""
return somDiv(n) == 1
def estChanceux(n) :
"""Retourne True si <n> est chanceux, False sinon."""
est_chanceux = True
for i in range(0, n-1) :
est_chanceux = est_chanceux and estPremier(n + i + i*i)
return est_chanceux
# Auto-test ===================================================================
if name ==' main ' :
from verif_m import verif
verif(somDiv(12), 16)
verif(estParfait(6), True)
verif(estPremier(31), True)
verif(estChanceux(11), True)
# import
from parfait_chanceux_m import estParfait, estChanceux
✦
ANNEXE F
Glossaire
Lexique bilingue
>>
> Invite Python par défaut dans un shell interactif. Souvent utilisée dans les exemples de
code extraits de sessions de l’interpréteur Python.
… Invite Python par défaut dans un shell interactif, utilisée lorsqu’il faut entrer le code
d’un bloc indenté ou à l’intérieur d’une paire de parenthèses, crochets ou accolades.
2to3 Un outil qui essaye de convertir le code Python 2.x en code Python 3.x en gérant la
plupart des incompatibilités qu’il peut détecter.
2to3 est disponible dans la bibliothèque standard lib2to2; un point d’entrée autonome est
Tool/s-cipts/2to3. Voir 2to3 – Automated Python 2 to 3 code translation.
l’entier 3, mais dans 3+4.5, chaque argument est d’un type différent (l’un int et l’autre float) et
tous deux doivent être convertis dans le même type avant d’être additionnés, sinon une
exception TypeError sera lancée. Sans coercition, tous les arguments, même de types
compatibles, doivent être normalisés à la même valeur par le programmeur, par exemple,
float(3)+4.5au lieu de simplement
3+4.5.
complex number (nombre complexe)
Une extension du système familier des nombres réels dans laquelle tous les nombres sont
exprimés comme la somme d’une partie réelle et une partie imaginaire. Les nombres
imaginaires sont des multiples réels de l’unité imaginaire (la racine carrée de -1), souvent
écrite i par les mathématiciens et j par les ingénieurs. Python a un traitement incorporé des
nombres complexes, qui sont écrits avec cette deuxième notation ; la partie imaginaire est
écrite avec un suffixe j, par exemple 3+1j. Pour avoir accès aux équivalents complexes des
éléments du module math utilisez le module cmath. L’utilisation des nombres complexes est
une possibilité mathématique assez avancée. Si vous n’êtes pas certain d’en avoir besoin
vous pouvez les ignorer sans risque.
context manager (gestionnaire de contexte)
Objet qui contrôle l’environnement indiqué par l’instruction with et qui définit les méthodes
en-ter ()et exit (). Voir la PEP 343.
CPython (Python classique)
Implémentation canonique du langage de programmation Python. Le terme CPython est
utilisé dans les cas où il est nécessaire de distinguer cette implémentation d’autres comme
Jython ou IronPython.
decorator (décorateur)
Fonction retournant une autre fonction habituellement appliquée comme une
transformation util- isant la syntaxe @wrapper.
classmethod() et staticmethod() sont des exemples classiques de décorateurs.
Les deux définitions de fonctions suivantes sont sémantiquement
def f(...) :
...
f = staticmethod(f)
@staticmethod
def f(...) :
...
équivalentes :
Un concept identique existe pour les classes mais est moins utilisé. Voir la documentation
function definition et class definition pour plus de détails sur les décorateurs.
descriptor (descripteur)
Tout objet qui définit les méthodes get (), set () ou delete (). Lorsqu’un attribut d’une classe
est un descripteur, un comportement spécifique est déclenché lors de la consultation de
l’at- tribut. Normalement, écrire a.b consulte l’objet b dans le dictionnaire de la classe de a,
mais si best un descripteur, la méthode get () est appelée. Comprendre les descripteurs est
fondamental pour la compréhension profonde de Python, car ils sont à la base de
nombreuses caractéristiques, comme les fonctions, les méthodes, les propriétés, les
méthodes de classe, les méthodes statiques et les références aux super-classes.
Pour plus d’informations sur les méthodes des descripteurs, voir Implementing Descriptors.
dictionary (dictionnaire)
Une table associative, dans laquelle des clés arbitraires sont associées à des valeurs.
L’utilisation des objets dict ressemble beaucoup à celle des objets list, mais les clés peuvent
être n’importe quels objets ayant une fonction hash (), non seulement des entiers. Ces tables
sont appelées hash en Perl.
docstring (chaîne de documentation)
Chaîne littérale apparaissant comme première expression d’une classe, d’une fonction ou
d’un mod- ule. Bien qu’ignorée à l’exécution, elle est reconnue par le compilateur et
incluse dans l’attribut
doc de la classe, de la fonction ou du module qui la contient. Depuis qu’elle est disponible
via l’introspection, c’est l’endroit canonique pour documenter un objet.
du -typing (typage « comme un canard »)
Style de programmation pythonique dans lequel on détermine le type d’un objet par
Glossaire 115
inspection de ses méthodes et attributs plutôt que par des relations explicites à des types
(« s’il ressemble à un
116 Glossaire
canard et fait coin-coin comme un canard alors ce doit être un canard »). En mettant l’accent
sur des interfaces plutôt que sur des types spécifiques on améliore la flexibilité du code
en permettant la substitution polymorphe. Le duck-typing évite les tests qui utilisent type() ou
isinstance() (notez cependant que le duck-typing doit être complété par l’emploi des classes
de base abstraites). À la place, il emploie des tests comme hasattr() et le style de
programmation EAFP.
EAFP (Easier to ask for forgiveness than permission, ou « plus facile de demander pardon que
la permis- sion »)
Ce style courant de programmation en Python consiste à supposer l’existence des clés
et des at- tributs nécessaires à l’exécution d’un code et à attraper les exceptions qui se
produisent lorsque de telles hypothèses se révèlent fausses. C’est un style propre et rapide,
caractérisé par la présence de nombreuses instructions try et except. Cette technique
contraste avec le style LBYL, courant dans d’autres langages comme le C.
expression (expression)
Fragment de syntaxe qui peut être évalué. Autrement dit, une expression est une
accumulation d’éléments d’expression comme des littéraux, des noms, des accès aux
attributs, des opérateurs ou des appels à des fonctions retournant une valeur. À l’inverse
de beaucoup d’autres langages, toutes les constructions de Python ne sont pas des
expressions. Les instructions ne peuvent pas être util- isées comme des expressions (par
exemple if). Les affectations sont aussi des instructions, pas des expressions.
extension module (module d’extension)
Module écrit en C ou en C++, utilisant l’API C de Python, qui interagit avec le cœur du
langage et avec le code de l’utilisateur.
finder
Objet qui essaye de trouver le loader (chargeur) d’un module. Il doit implémenter une
méthode nommée find_module(). Voir la PEP 302 pour des détails et [Link] pour
une classe de base abstraite.
floor division (division entière)
Division mathématique qui laisse tomber le reste. L’opérateur de division entière est //. Par
exemple, l’expression 11//4est évaluée à 2, par opposition à la division flottante qui retourne
2.75.
function (fonction)
Suite d’instructions qui retourne une valeur à l’appelant. On peut lui passer zéro ou plusieurs
argu- ments qui peuvent être utilisés dans le corps de la fonction. Voir aussi argument et
method.
future
Un pseudo-module que les programmeurs peuvent utiliser pour permettre les nouvelles
fonction- nalités du langage qui ne sont pas compatibles avec l’interpréteur couramment
employé.
En important future et en évaluant ses variables, vous pouvez voir à quel moment une
carac- téristique nouvelle a été ajoutée au langage et quand est-elle devenue la
>>> import future
>>> future .division
_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)
GIL
Cf. global interpreter lo .
global interpreter lo (verrou global de l’interpréteur)
Le verrou utilisé par les threads Python pour assurer qu’un seul thread tourne dans la
ma ine virtuelle CPython à un instant donné. Il simplifie Python en garantissant que deux
processus ne peuvent pas accéder en même temps à une même mémoire. Bloquer
l’interpréteur tout entier lui permet d’être multi-thread aux frais du parallélisme du système
environnant. Des efforts ont été faits par le passé pour créer un interpréteur free-threaded
(où les données partagées sont verrouillées avec une granularité fine), mais les
performances des programmes en souffraient considérablement, y compris dans le cas des
programmes mono-thread.
hashable (hachable)
Un objet est hachable s’il a une valeur de hachage constante au cours de sa vie (il a besoin
d’une méthode hash ()) et s’il peut être comparé à d’autres objets (il a besoin d’une méthode
eq ()). Les objets hachables comparés égaux doivent avoir la même valeur de hachage.
L’hachabilité rend un objet propre à être utilisé en tant que clé d’un dictionnaire ou membre
d’un ensemble (set), car ces structures de données utilisent la valeur de hachage de façon
interne.
Tous les objets de base Python non modifiables (immutable) sont hachables, alors que
certains conteneurs comme les listes ou les dictionnaires sont modifiables. Les objets
instances des classes définies par l’utilisateur sont hachables par défaut ; ils sont tous
inégaux (différents) et leur valeur de hachage est leur id().
IDLE
Un environnement de développement intégré pour Python. IDLE est un éditeur basique et
un en- vironnement d’interprétation ; il est donné avec la distribution standard de Python.
Excellent pour les débutants, il peut aussi servir d’exemple pas trop sophistiqué pour tous
ceux qui doivent implé- menter une application avec interface utilisateur graphique multi-
plate-forme.
immutable (immuable)
Un objet avec une valeur fixe. Par exemple, les nombres, les chaînes, les tuples. De tels
objets ne peuvent pas être altérés ; pour changer de valeur un nouvel objet doit être créé.
Les objets immuables jouent un rôle important aux endroits où une valeurs de hash
constantes est requise, par exemple pour les clés des dictionnaires.
importer
Objet qui à la fois trouve et charge un module. C’est à la fois un objet finder et un objet
loader.
interactive (interactif)
Python possède un interpréteur interactif, ce qui signifie que vous pouvez essayer vos idées
et voir immédiatement les résultats. Il suffit de lancer python sans argument (éventuellement
en le sélec- tionnant dans un certain menu principal de votre ordinateur). C’est vraiment
un moyen puissant pour tester les idées nouvelles ou pour inspecter les modules et les
paquetages (pensez à help(x)).
interpreted (interprété)
Python est un langage interprété, par opposition aux langages compilés, bien que cette
distinction puisse être floue à cause de la présence du compilateur de bytecode. Cela
signifie que les fichiers source peuvent être directement exécutés sans avoir besoin de
créer préalablement un fichier binaire exécuté ensuite. Typiquement, les langages
interprétés ont un cycle de développement et de miseau point plus court que les langages
compilés mais leurs programmes s’exécutent plus lentement. Voir aussi interactive.
iterable
Un objet conteneur capable de renvoyer ses membres un par un. Des exemples
d’iterable sont les types séquences (comme les list, les str, et les tuple) et quelques types
qui ne sont pas desséquences, comme les objets dict, les objets file et les objets de n’importe
quelle classe que vous définissez avec une méthode iter () ou une méthode getitem (). Les
iterables peuvent être utilisés dans les boucles for et dans beaucoup d’autres endroits où
une séquence est requise (zip(), map(), . . .). Lorsqu’un objet iterable est passé comme
argument à la fonction incorporée iter() il renvoie un itérateur. Cet itérateur est un bon
moyen pour effectuer un parcours d’un ensemble de valeurs. Lorsqu’on utilise des
Glossaire 119
iter() ni de manipuler directement les valeurs en question. L’instruction for fait cela
automatique- ment pour vous, en créant une variable temporaire sans nom pour gérer
l’itérateur pendant la durée de l’itération. Voir aussi iterator, sequence, et generator.
iterator (itérateur)
Un objet représentant un flot de données. Des appels répétés à la méthode next () de
l’itéra- teur (ou à la fonction de base next()) renvoient des éléments successifs du flot.
Lorsqu’il n’y a plus de données disponibles dans le flot, une exception StopIteration est lancée.
À ce moment-là, l’ob- jet itérateur est épuisé et tout appel ultérieur de la méthode next() ne
fait que lancer encore une exception StopIteration. Les itérateurs doivent avoir une méthode
iter () qui renvoie l’objet itérateur lui-même. Ainsi un itérateur est itératif et peut être utilisé
dans beaucoup d’endroits où les iterables sont acceptés ; une exception notable est un
code qui tenterait des itérations multiples. Un objet conteneur (comme un objet list) produit
un nouvel itérateur à chaque fois qu’il est passé à la fonction iter()ou bien utilisé dans une
boucle for. Si on fait cela avec un itérateur on ne récupérera que le même itérateur épuisé
utilisé dans le parcours précédent, ce qui fera apparaître le conteneur comme s’il était vide.
keyword argument (argument avec valeur par défaut)
Argument précédé par variable_name= dans l’appel. Le nom de la variable désigne le nom local
dans la fonction auquel la valeur est affectée. ** est utilisé pour accepter ou passer un
dictionnaire d’arguments avec ses valeurs. Voir argument.
lambda
Fonction anonyme en ligne ne comprenant qu’une unique expression évaluée à l’appel.
Syntaxe de création d’une fonction lambda :
lambda[arguments]: expression
engendre une liste de chaînes contenant les écritures hexadécimales des nombres pairs de
l’intervalle de 0 à 255. La clause if est facultative. Si elle est omise, tous les éléments de
l’intervalle range(256)seront traités.
loader (chargeur)
Objet qui charge un module. Il doit posséder une méthode load_module(). un loader est
typiquement fournit par un finder. Voir la PEP 302 pour les détails et voir
[Link] pour une classe de base abstraite.
mapping (liste associative)
Un objet conteneur (comme dict) qui supporte les recherches par des clés arbitraires en
utilisant la méthode spéciale getitem ().
metaclass
La classe d’une classe. La définition d’une classe crée un nom de classe, un dictionnaire et
une liste de classes de base. La métaclasse est responsable de la création de la classe à
partir de ces trois éléments. Beaucoup de langages de programmation orientés objets
fournissent une implémentation par défaut. Une originalité de Python est qu’il est possible
de créer des métaclasses personnalisées. Beaucoup d’utilisateurs n’auront jamais besoin
de cela mais, lorsque le besoin apparaît, les méta- classes fournissent des solutions
puissantes et élégantes. Elles sont utilisées pour enregistrer les accès aux attributs, pour
ajouter des threads sécurisés, pour détecter la création d’objet, pour implé- menter des
singletons et pour bien d’autres tâches.
Plus d’informations peuvent être trouvées dans Customizing class creation.
Glossaire 121
method (méthode)
Fonction définie dans le corps d’une classe. Appelée comme un attribut d’une instance de
classe, la méthode prend l’instance d’objet en tant que premier argument (habituellement
nommé self). Voir function et nested scope.
mutable (modifiable)
Les objets modifiables peuvent changer leur valeur tout en conservant leur id(). Voir
aussi im- mutable.
named tuple (tuple nommé)
Toute classe de pseudo-tuples dont les éléments indexables sont également accessibles
par des at- tributs nommés (par exemple [Link]() retourne un objet pseudo-tuple où
l’année est ac- cessible soit par un index comme t[0]soit par un attribut nommé comme
t.tm_year.
Un tuple nommé peut être un type de base comme time.struct_time ou il peut être créé par une
définition de classe ordinaire. Un tuple nommé peut aussi être créé par la fonction fabrique
[Link](). Cette dernière approche fournit automatiquement des caractéristiques
supplé- mentaires comme une représentation auto-documentée, par exemple :
>>> Employee(name='jones', title='programmer')
for i in range(len(food)) :
print(food[i])
view (vue)
Les objets retournés par [Link](), [Link]() et [Link]() sont appelés des dictionary views.
ce sont des « séquences paresseuses 1 » qui laisseront voir les modifications du dictionnaire
sous-jacent. Pour forcer le dictionary view à être une liste complète, utiliser list(dictview). Voir
Dictionary view objects.
virtual ma ine (machine virtuelle)
Ordinateur entièrement défini par un programme. la machine virtuelle Python exécute le
bytecode généré par le compilateur.
1. L’évaluation paresseuse est une technique de programmation où le programme n’exécute pas de code avant que
les résultats de ce code ne soient réellement nécessaires. Le terme paresseux (en anglais lazzy evaluation) étant connoté
négativement en français on parle aussi d’évaluation retardée.
Glossaire 123
Zen of Python
Une liste de principes méthodologiques et philosophiques utiles pour la compréhension et
l’utili- sation du langage Python. Cette liste peut être obtenue en tapant import this dans
l’interpréteur Python.
124 Glossaire
Webographie
• Les sites généraux
: [Link]
[Link]/py
pi
[Link]/p/pythonxy/wiki/Downloads
• Interpréteur et EDI
spécialisés : IP[y]thon
Spyder
Wing IDE 101
SciTE
PyScripter
• Les outils :
matplotlib
inkscape
rst2pdf
TeXnicCent
er
• Le lien des
liens : Liens
Python
Bibliographie
' échappé
couples clé/vale ur
non modifiable,
pour nomsordonnée
séquence de variables,
de caractères
Identificateurs Conversions
fonctions, modules, classes…
a‥zA‥Z_ suivi de a‥zA‥Z_0‥9
Affectation de variables
la séquence en paramètre
variables
incrémentation
index négatif -6 -5 -4 -3 -2 -1
index positif 0 1 2 3 4 5
tranche positive
tranche négative
☝ nombres flottants… valeurs approchées ! angles en radians Maths # bloc sinon si expression logique x>0 vraie
%
# bloc sinon si variable booléenne bTermine vraie
tant que la condition est vraie chaque élément d'un conteneur ou d'un itérateur
while expression for variable in séquence:
logique:
condition avec au moins une valeur variable continue s = "Du initialisations avant la boucle
(ici i) itération
suivante
texte" cpt = 0
while i <= 100:
variable de boucle, valeur gérée par l'instruction for
# bloc exécuté tant que i ≤ i=100 for c in s:
100
s= ∑ i2
s = s + i**2 if c == "e": Comptage du
i = i + 1 ☝ faire varier la cpt = cpt + nombre de edans la
variable 1 chaîne.
☝ attention aux boucles sans fin ! utilisation des tranches pour parcourir un sous-ensemble de la séquence
Parcours des index de la séquence
Affichage / Saisie ◽ changement de l'élément à la position
print("v=",3,"cm :",x,",",y+4) ◽ accès aux éléments autour de la position (avant/après)
lst = [11,18,9,12,23,4,17]
éléments à afficher : valeurs littérales, variables, perdu = []
for idx in Bornage des
expressions Options de print: valeurs
◽ sep=" " (séparateur d'éléments, défaut espace) range(len(lst)): val =
supérieures à 15,
◽ end="\n" (fin d'affichage, défaut fin de ligne) lst[idx]
mémorisation des
if val> 15:
◽ file=f (print vers fichier, défaut sortie standard) valeurs perdues.
[Link](va
l) lst[idx] = 15
s = input("Directives:") print("modif:",lst,"-modif:",perdu)
☝ input retourne toujours une chaîne, la convertir vers le type Parcours simultané index et valeur de la séquence:
désiré (cf encadré Conversions au recto). for idx,val in enumerate(lst):
nb d'éléments Opérations sur conteneurs très utilisé pour les Génération de séquences d'entiers
Note: Pour dictionnaires et ensembles, boucles itératives for
ces opérations travaillent sur les clés.
→ booléen, opérateur de test de présence d'absence)
Opérations sur dictionnaires Opérations sur ensembles # bloc instructions, calcul de res, etc.
clé valeu Opérateurs:
retourner None
i e à jou /ajout
de couple < <= > >= → relations d'inclusion
vue u le clé , clé pp l d fon ion
valeu , couple clé
clé clé