Introduction `a l’algorithmique et `a la programmation
SHNU, 2019 – 2020
Anthony Labarre
Anthony.Labarre@u-pem.fr
– Cours 2 –
– Rappels du premier cours –
I On a vu :
I les variables et leurs types ;
I les branchements conditionnels (if / elif / else) ;
I les chaˆınes, lesrangeet les bouclesfor;
I l’interpr ´eteur Python ;
I comment installer et configurer Python 3 et Geany ;
I comment structurer un programme Python ;
Des questions ?
– Plan d’aujourd’hui –
Les chaˆınes de caract `eres Les tuples
Les listes
Bouclesfor(suite) Les fonctions Les doctests Les modules
Python pas `a pas
Les chaˆınes de caract `eres
– D ´eclaration de chaˆınes de caract `eres –
I On peut d ´eclarer une chaˆıne :
I entre apostrophes : x = 'toto'
I ou entre guillemets : x = "toto"
I Et si la chaˆıne contient des'et des"? On utilise les caract `eres sp ´eciaux\'et\":
s = 'il a dit : "J\'ai faim!"'
I Attention :\'compte pour un seul caract `ere, de m ˆeme que\"(ce sont des caract `eres sp ´eciaux) ;
– D ´eclaration sur plusieurs lignes –
I On peut d ´eclarer une chaˆıne sur plusieurs lignes en utilisant des triples apostrophes ou triples guillemets comme d ´elimiteurs :
Exemple
s = '''Ceci est une chaˆıne sur
plusieurs lignes.''' t = """Ceci
fonctionne aussi."""
I Les sauts de lignes seront encod ´es par le caract `ere\n;
– Caract `eres sp ´eciaux –
I Voici quelques caract `eres sp ´eciaux utiles :
\' apostrophe \" guillemet
\n saut de ligne \t tabulation
\\ backslash \b reculer d’un
Utilisation de\b
>>> x = 'toto\ba'
>>> x
'toto\x08a'
>>> print(x)
'tota'
>>> len(x)
6 # normal: \b compte pour un caract`ere
– Acc `es aux caract `eres –
I Une chaˆıne est un it ´erable de caract `eres :
indices : 0 1 2 3 4 5 6
´el ´ements : b o n j o u r
I Attention, les indices (positions) sont des entiers de 0 `a n−1 pour une chaˆıne dencaract `eres !
I Pour connaˆıtre la longueur des: on appellelen(s);
I Pour acc ´eder `a l’ ´el ´ement num ´eroi: on utilises[i];
Exemple
>>> s = 'bonjour'
>>> s[0]
'b'
>>> s[2]
'n'
>>> s[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
– It ´erer sur des chaˆınes –
I On peutit ´erer sur(parcourir) des chaˆınes de deux fac¸ons :
Exemple (it ´erer sur les positions)
>>> texte = "bonjour\n"
>>> for position in range(len(texte)):
... print(texte[position], end='') ...
bonjour
Exemple (it ´erer sur les ´el ´ements)
>>> texte = "bonjour\n"
>>> for lettre in texte:
... print(lettre, end='') ...
bonjour
– Les chaˆınes sont non-modifiables –
Les chaˆınes ne sont pas modifiables !
I Sixcontient une valeur de typestret que vous voulez la changer, il faut faire une nouvelle affectation dex:
Exemple
>>> x = 'toto'
>>> x[0] = 'p'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> x = 'poto' # fonctionne
– L’op ´erateur in –
I Remarque : l’op ´erateurinpermet de faire deux choses : 1. parcourir un it ´erable (avec unfor) ;
2. v ´erifier si un ´el ´ement appartient `a un it ´erable ;
I Dans la seconde utilisation :
x in iterable−→True ⇔ x∈iterable
Exemple
>>> '2' in ('1', '2', '3', '4')
True
>>> 2 in ('1', '2', '3', '4')
False
>>> 2 in 1234 # les entiers ne sont PAS it´erables
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: argument of type 'int' is not iterable
Python pas `a pas
Les tuples
– Les tuple –
I Les chaˆınes ne nous permettent de stocker que du texte ;
I Lestuplesont des it ´erables comme les chaˆınes, mais pouvant contenir n’importe quel type ;
Exemple (d ´eclaration de tuples)
>>> x = (4, 3, 1) # cr´ee un tuple avec 3 entiers
>>> x = 4, 3, 1 # mˆeme r´esultat
>>> y = (4,) # tuple avec un seul ´el´ement
>>> z = (None, "shnu", 3.14, 42) # m´elange de types
I Pour cr ´eer untupleavecun seul ´el ´ement, il faut utiliser une virgule, sinon on obtient un entier ;
I Comme les chaˆınes :
I x[i]donne l’ ´el ´ement en positioni;
I len(x)donne la longueur du tuple ;
I les tuples sont non modifiables ;
– Affectations multiples –
I La notation des tuples permet d’affectersimultan ´ement plusieurs variables comme ceci :x, y, z = iterable
I Il faut lem ˆeme nombred’ ´el ´ements `a gauche et `a droite ;
Exemple
>>> x, y, z = [5, 6, 8]
>>> x, y, z = 5, 6, 8 # mˆeme r´esultat
>>> x, y = y, x # ´echange les valeurs de x et y
>>> x, y = 1, 2, 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
>>> x, y, z = 1, 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
– ´ Ecriture condens ´ee –
I En parlant de raccourcis, Python propose aussi des notations abr ´eg ´ees pour les affectations ;
I Voici quelques exemples avecxentier etschaˆıne de caract `eres :
x += 3 ≡ x = x + 3 x *= 2 ≡ x = x * 2
x //= 4 ≡ x = x // 4
s += 'toto' ≡ s = s + 'toto' s *= 3 ≡ s = s * 3
s //= 4 −→ erreur
I Il n’y a pas de notationi++ou++ien Python;
Python pas `a pas
Les listes
– Pr ´esentation –
I Leslistessont des tuples modifiables : on les cr ´ee comme les tuples, mais avec des crochets au lieu de parenth `eses :
Exemple
>>> lst1 = [3, 'toto', 4.5, False] # liste `a 4 ´el´ements
>>> lst2 = [] # liste vide
>>> lst3 = list() # liste vide
I Comme les chaˆınes et les tuples :
I x[i]donne l’ ´el ´ement en positioni;
I len(x)donne la longueur de la liste ;
I l’op ´erateurinmarche comme avant ;
– Affectations et listes –
I On peut modifier une liste `a l’aide des crochets :
Exemple
>>> liste_3 = [1, 2.0, '3']
>>> liste_3
[1, 2.0, '3']
>>> liste_3[0] = -5
>>> liste_3
[-5, 2.0, '3']
– Affectations et objets modifiables –
Il y a des subtilit ´es ici, `a bien travailler.
I Que se passe-t-il quand on ´ecrit l’affectationy = x?
I Sixest non-modifiable : on copie le contenu dexdansy;
I Sixest modifiable :xetyd ´esignentla m ˆeme chose !;
Exemple
>>> lst = [3, 'toto', 4.5, False]
>>> lst2 = lst
>>> lst2[1] = 'titi'
>>> print(lst)
[3, 'titi', 4.5, False]
[Visualisation sur PythonTutor]
I On peut obtenir une “vraie” copie aveclist(); [Visualisation sur PythonTutor]
– Ajouter des ´el ´ements `a des listes –
I Lesm ´ethodessuivantes des listes permettent d’y ajouter des ´el ´ements :
1. lst.append(x): ajoute la valeur dex `a la fin delst; 2. lst.extend(iterable): ajoute tous les ´el ´ements de
iterable `a la fin delst;
3. lst.insert(i, elem): ajouteelemen positioni;
Exemple
>>> lst = list()
>>> lst.append(3)
>>> lst.extend(range(3))
>>> lst.insert(2, "bonjour")
>>> lst
[3, 0, 'bonjour', 1, 2]
– Supprimer des ´el ´ements d’une liste –
I Les m ´ethodes suivantes des listes permettent de supprimer des ´el ´ements :
1. lst.pop(): supprime le dernier ´el ´ement delstet renvoie sa valeur ;
2. lst.pop(i): supprime lei- `eme ´el ´ement delstet renvoie sa valeur ;
3. lst.remove(x): supprime la premi `ere occurrence dex dans la liste si elle le contient (sinon, provoque une erreur) ;
Exemple
>>> lst = [3, 0, 'bonjour', 'bonjour', 1, 2]
>>> lst.pop()
2
>>> lst.pop(0)
3
>>> lst.remove("bonjour")
>>> lst
[0, 1, 'bonjour']
– Transtypage entre it ´erables –
I Comme pour les entiers, r ´eels, ..., on peut transformer un it ´erable en un autre it ´erable ;
I On utilise pour cela les fonctions correspondantes (list, str,tuple) ;
Exemple
>>> list((1, 2, 3))
[1, 2, 3]
>>> tuple([4, 5, 6])
(4, 5, 6)
>>> list('abc')
['a', 'b', 'c']
>>> tuple('def')
('d', 'e', 'f')
>>> str([7, 8, 9])
'[7, 8, 9]'
Python pas `a pas
Bouclesfor (suite)
– Affectations dans un for –
Unfor ne peut pas modifier une liste sans utiliser les indices.
Exemple
>>> liste = [1, 2, 3]
>>> for element in liste:
... element += 1 ...
>>> liste
[1, 2, 3]
>>> for i in range(len(liste)):
... liste[i] += 1 ...
>>> liste
[2, 3, 4]
– break et continue –
I Il existe deux moyens pour interrompre une boucle :
I breakarr ˆete la boucle et reprend donc l’ex ´ecution du programme apr `es la boucle ;
I continuearr ˆete l’it ´eration en cours (on “continue” `a l’it ´eration suivante de la boucle) ;
for ...:
break
suite du programme
for ...:
continue
suite du programme
– Un exemple avec break –
I Exemple d’utilisation : si on cherche `a savoir si une liste contient un nombre sup ´erieur `a 10, rien ne sert de poursuivre les
recherches une fois qu’on en a trouv ´e un :
Exemple (trouver un ´el ´ement>10)
# lst = ...
for element in lst:
if element > 10:
print("J'ai trouv´e", element,
"dans la liste, qui est sup´erieur `a 10") break
– Un exemple avec continue –
I Exemple d’utilisation : n’afficher que les ´el ´ements d’une liste qui ne sontpasdes chaˆınes :
Exemple (afficher une liste (sauf ses chaˆınes))
# lst = ...
for element in lst:
if type(element) is str:
continue print(element)
Python pas `a pas
Les fonctions
– Pr ´esentation g ´en ´erale –
I Unefonctionest unbloc d’instructions r ´eutilisable; X Une foisbien test ´ee, on s’en ressertautant qu’on veut; X Maintenance`a effectuer `aun seul endroit;
X On peut les regrouperdans un modulepourles r ´eutiliser;
I On a d ´ej `a utilis ´e des fonctions de Python (print,input, ...) ; voyons maintenant comment cr ´eer les n ˆotres ;
– D ´efinir et appeler une fonction –
I On d ´efinit une fonction `a l’aide d’un bloc comme suit :
Syntaxe pour d ´efinir une fonction def nom_fonction():
# instruction 1 de la fonction
# instruction 2 de la fonction
# ...
# instruction n de la fonction
I Important :lors de la d ´efinition d’une fonction, le code n’est pasex ´ecut ´e ;
I Onappelleensuite la fonction avec la commande nom_fonction();
I Les r `egles vues pour nommer les variables s’appliquent aux fonctions ;
– Premier exemple –
Exemple (utilisation d’une fonction)
def appel():
print('-' * 5, 'appel', '-' * 5)
if __name__ == "__main__":
print('bonjour') appel()
n = int(input('nombre = ')) for i in range(n):
appel()
I Chaque fois qu’on utiliseappel(), le programme
interrompt le flot normal d’instructionspour aller effectuer les instructions d’appel();
I Une fois les instructions d’appel()effectu ´ees, le programmereprend l `a o `u il en ´etait;
[Visualisation sur PythonTutor]
– Fonction avec param `etre(s) –
I Une fonction peut avoir un ou plusieursparam `etres;
Exemple
def affiche(message):
print('*' * (len(message) + 4)) print('* ' + message + ' *') print('*' * (len(message) + 4))
if __name__ == "__main__":
affiche('bonjour')
texte = input("Entrez un message:") affiche(texte)
I Ils sont nomm ´esentre parenth `esesdans la d ´efinition de la fonction ;
I Lorsque l’on appelle la fonction, il fautpasser les param `etres(le bon nombre et dans l’ordre !) entre parenth `eses ;
– Fonctionnement des param `etres –
Lors de l’appel de la fonction, les valeurs desargumentssont copi ´es dans lesparam `etres; l’appel suivant :
def fonction(p_1, p_2, ...):
# code de la fonction
# ...
fonction(a_1, a_2, ...) # appel
´equivaut donc `a :
p_1 = a_1 p_2 = a_2
# pareil pour les p_i, a_i suivants
# ...
# code de la fonction
– L’instruction return –
I La fonction peut communiquer des r ´esultats avec l’instructionreturnx;
1. elle interrompt l’ex ´ecution de la fonction ;
2. ellerenvoiela valeurx(de n’importe queltype) ;
Exemple
>>> def plus_un(x):
... return x + 1 ...
>>> plus_un(3)
4
>>> y = plus_un(5)
>>> y 6
>>> plus_un(1) + plus_un(2)
5
I Si on n’ ´ecrit pas dereturnou si on ´ecritreturnsans
– Port ´ee des variables –
Attention il y a des subtilit ´es ici, `a bien travailler.
Exemple
def f(n):
n = n + 1
if __name__ == "__main__":
x = 3
print(f(n))
print('x vaut', x)
I Le programme produit une erreur !
I `a l’appel de la fonction, la valeur du param `etre defest affect ´ee aunde lad ´efinitiondef;
I ... maisnn’existe pas dans le corps du programme ; [Visualisation sur PythonTutor]
– Port ´ee des variables –
Attention il y a des subtilit ´es ici, `a bien travailler.
Exemple
def f(n):
n = n + 1
if __name__ == "__main__":
n = 3 f(n)
print('n vaut', n)
I Le r ´esultat estn vaut 3 !
I `a l’appel def, la valeur dun“principal” est affect ´ee aunde lad ´efinitiondef, qu’on notenf;
I Cen’est pasle m ˆemen:nf prend la valeur den `a l’appel defet augmente de 1.nne change pas.
– Port ´ee des variables –
Attention il y a des subtilit ´es ici, `a bien travailler.
Exemple
def f(x):
n = 1
if __name__ == "__main__":
n = 3 f(n)
print('n vaut', n)
I Le r ´esultat esttoujoursn vaut 3 !
I `a l’appel de la fonction, la valeur du param `etre defest affect ´ee auxde lad ´efinitiondef;
I l’affectationn = 1cr ´ee une variablelocale `af, not ´eenf;
I nf prend la valeur de 1 et lenprincipal ne change pas.
[Visualisation sur PythonTutor]
– Port ´ee des variables –
I Lorsqu’on est dans un appel de fonction :
I Ses param `etres sont desvariables locales;
I Ses variables affect ´ees sont aussi desvariables locales;
I Ces variables locales existentpendant l’ex ´ecution de la fonctionet n’existent plus apr `es ;
I Les variables affect ´ees dans le corps du programme (hors fonctions) sont desvariables globales;
I elles sontlisiblesdans tout le programme ;
I elles ne sontpas modifiablesdans une fonction ;
I en effet, affecter unevariable globaledans une fonction cr ´ee unevariable localeavec le m ˆeme nom ;
I Laport ´eed’une variable est la partie du programme o `u elle existe ;
– Sch ´ema des port ´ees dans un programme –
I Le sch ´ema ci-dessous illustre les port ´ees du programme et de ses fonctions (donc les zones o `u leurs variables existent) :
# des variables ici
def fonction_1(parametres_1):
# variables de la fonction 1
def fonction_2(parametres_2):
# variables de la fonction 2 if __name__ == '__main__':
# et des variables l`a
port ´ee du programme
port ´ee de la fonction 1
port ´ee de la fonction 2
I Evitez les variables globales, surtout si elles sont modifiables !´
– Pourquoi une fonction main ? –
I Le slide pr ´ec ´edent montre que les variables d ´efinies sousif __name__ == "__main__"sont globales !
I C’est pourquoi la forme suivante est recommand ´ee ;
# imports, fonctions, variables, ...
def main():
# le programme principal if __name__ == "__main__":
main()
I Sinon, les variables demainseraient modifiables par d’autres fonctions !
Python pas `a pas
Les doctests
– Tester ses fonctions –
I Quand on ´ecrit un programme, il est n ´ecessaire de le testerpour rep ´erer et r ´egler les probl `emes ;
I En Python, il est facile d’ ´ecrire des tests pour chaque fonction ;
I On teste chaque fonction s ´epar ´ement `a l’aide du module doctest;
– Un exemple simple pour les doctests –
I Supposons qu’on a ´ecrit une fonctionaddition(a, b), qui renvoie la valeur dea + b;
I Pour v ´erifier qu’elle fonctionne correctement, on la v ´erifie sur quelques exemples simples :
Exemple (Test d’une fonction dans l’interpr ´eteur)
>>> addition(3, 5)
8
>>> addition(0, 0)
0
>>> addition(-4, 2)
-2 ...
– Structure des doctests –
Exemple (Test d’une fonction dans l’interpr ´eteur)
>>> addition(3, 5)
8
>>> addition(0, 0)
0
>>> addition(-4, 2)
-2 ...
En g ´en ´eral, le format est :
Syntaxe d’un doctest
>>> [test (expression, appel de fonction, ...)]
r´esultat attendu
– Emplacement des doctests –
I On peut placer des doctests :
1. dans la documentation des fonctions (lesdocstrings, voir plus loin) ;
2. dans des fichiers s ´epar ´es (par exemple au format.txt) ;
I Comment choisir ? En pratique :
I on laisse quelquesexemplesdans les docstrings ;
I on place les autres “vrais” tests dans des fichiers s ´epar ´es, surtout s’ils sont nombreux ;
– Les docstrings –
I Les docstrings documentent les fonctions ; c’est le texte qui apparaˆıt quand on ex ´ecute la commande
help(nom_de_fonction);
I Ondoitles placer au d ´ebut de la fonction !
Exemple (docstring)
def ma_fonction(x):
"""Renvoie x ** 2. x doit ˆetre un nombre."""
return x ** 2
– Les docstrings –
I Les exemples sous forme de doctests font partie de la documentation ; on les place donc aussi dans les docstrings ;
Exemple (docstring demath.factorial)
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0 [... autres doctests ... ]
"""
doctest 1
doctest 2
doctest 3
– Ex ´ecution des doctests –
I Pour ex ´ecuter les tests du fichierprogramme.py, on ex ´ecute la commande :
python3 -m doctest programme.py
I Le programme n’est pas ex ´ecut ´e : seulement ses doctests ;
I R ´esultat :
I si rien ne s’affiche, tout va bien ;
I sinon, on obtient les tests qui ont ´echou ´e avec les r ´esultats attendus ;
I On peut aussi ´ecrirepython3 -m doctest tests.txt pour les tests s ´epar ´es ;tests.txtdoit ˆetre dans le m ˆeme dossier queprogramme.py;
– Comment ´ecrire des tests ? –
I Plus un programme est v ´erifi ´e, plus on est convaincu qu’il fonctionne correctement ;
I En g ´en ´eral, on teste :
I des cas “simples” (v ´erifiables `a la main) ;
I des cas “particuliers” (divisions par z ´ero, valeurs n ´egatives, ...) ;
I et quand on peut, un grand nombre de donn ´ees al ´eatoires ;
Python pas `a pas
Les modules
– Modules –
I Unmoduleest un ensemble de fonctions d ´ej `a programm ´ees, pr ˆetes `a ˆetre utilis ´ees ;
I Python propose beaucoup demodules de base: (math, time,random, ...) ;
I On peut aussi en t ´el ´echarger sur Internet ou en cr ´eer facilement ;
– Utilisation de modules –
I Il y a trois fac¸ons d’utiliser une fonctionma fonctiond’un modulemon module:
1. frommon moduleimportma fonction: on utilise alors normalement la fonction ;
2. importmon module: la fonction s’appelle mon module.ma fonction;
3. frommon moduleimport*: comme 1, mais on charge toutesles fonctions du modulemon module;
– Renommage de modules : as –
L’import from mon module import * est d ´econseill ´e ! ! !
I Il peut cr ´eer des probl `emes : on peut ´ecraser des fonctions poss ´edant le m ˆeme nom !
I Si le nom du module vous d ´erange, vous pouvez utiliser as;
I Par exemple :
>>> import nombeaucouptroplong as nbtl
>>> x = nbtl.ma_fonction(12)
– Un exemple –
Exemple (modulemath) import math
if __name__ == "__main__":
print('pi = ', math.pi) print(math.cos(math.pi/4))
I math: les fonctions et les constantes math ´ematiques usuelles comme exp, cos,π, . . . ;
I random: des fonctions pour faire des tirages au sort ;
I time: pour mesurer le temps, connaˆıtre l’heure, ou attendre un certain temps ;
– Pourquoi “ if __name__ == '__main__' ” ? –
I Lorsque Python charge un module, il ex ´ecute tout le code ex ´ecutable qui s’y trouve ;
I Le modulemon modules’appelle :
I 'mon_module's’il est charg ´e comme module ;
I '__main__'s’il est charg ´e comme programme ;
I Mettre votre code dansmain()ou sousif __name__
== '__main__'permet de ne l’ex ´ecuterque quand on
´ecritpython3 mon module.py;
– Cr ´eer ses propres modules –
I Pour cr ´eer le modulemon module, il suffit d’ ´ecrire ses fonctions, constantes, ... dans un fichiermon module.py;
I Pour que Python le trouve, il doit ˆetre : 1. dans un r ´epertoire “standard” ;
2. ou dans le m ˆeme r ´epertoire que votreprogramme principal;
I Les r `egles vues pour nommer les variables s’appliquent aux modules ;