Introduction `a l’algorithmique et `a la programmation
SHNU, 2019 – 2020
Anthony Labarre
Anthony.Labarre@u-pem.fr
– Cours 3 –
– Clarifications sur les fonctions –
I
Rappel : on ne d ´eclare pas une fonction bar() dans une fonction foo() !
I
Si vous le faites, seule la fonction foo() connaˆıt la fonction bar() :
Exemple ( `a ne pas faire)
>>> def foo():
... def bar():
... return "valeur de bar"
... return bar() ...
>>> foo()
'valeur de bar'
>>> bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'bar' is not defined
– Clarifications sur les fonctions –
I
Ecrivez plut ˆot ceci : Exemple ( `a faire)
>>> def bar():
... return "valeur de bar"
...
>>> def foo():
... return bar() ...
>>> foo()
'valeur de bar'
>>> bar()
'valeur de bar'
– Plan d’aujourd’hui –
La boucle while
Structures de donn ´ees en Python Les ensembles
Les dictionnaires Slices
It ´erables en compr ´ehension
Python pas `a pas
La boucle while
– Boucle while –
I
On a d ´ej `a vu une instruction de boucle : la boucle for ; Syntaxe du for (≡ ∀ element ∈ iterable)
for element in iterable:
# instruction 1 du for
# instruction 2 du for
# ...
# suite du programme
I
Elle n’est h ´elas pas toujours utilisable ; par exemple :
I
quand on n’a pas d’it ´erable `a parcourir ;
I
quand on veut faire une boucle “infinie” ;
I
quand on ignore combien d’it ´erations seront n ´ecessaires ; .. .
I
Dans ces cas-l `a, on utilise une boucle while ;
– Structure de la boucle while –
I
La structure de la boucle while se pr ´esente comme suit : Syntaxe du while
while condition:
# instruction 1
# instruction 2
# ...
# suite
Organigramme
condition vraie ?
instructions
suite non
oui
I
On peut toujours remplacer un for par un while, mais c’est plus compliqu ´e ;
I
Attention : c’est `a vous de vous assurer que la boucle se
termine !
– Deux exemples –
Exemple (dix.py)
if __name__ == "__main__":
nbr = int(input('Combien ? ')) i = 1
while i <= nbr:
print('bonjour') i = i + 1
print('Fini !')
Exemple (boom.py)
from time import sleep if __name__ == "__main__":
nbr = int(input('Combien de secondes ? ')) i = nbr
while i > 0:
print(str(i) + '...') sleep(1)
i = i - 1
print('BOOOM !')
– Nombre d’it ´erations non fix ´e –
Le while est surtout utile quand on ne sait pas combien d’it ´erations seront n ´ecessaires :
Exemple (forcer l’utilisateur `a respecter les bornes)
if __name__ == "__main__":
a = int(input('Nombre entre 1 et 10 : ')) while a < 1 or a > 10:
a = int(input('Erreur, entre 1 et 10 :')) print('Bravo, votre nombre est ' + str(a))
Exemple (lancer deux d ´es pour obtenir 12)
from random import randint if __name__ == "__main__":
des = 0 nbr = 0
while des != 12:
des = randint(1, 6) + randint(1, 6) nbr = nbr + 1
print(nbr, 'tirages pour faire 12')
– Un exemple avec break (trouver.py) –
I
break et continue marchent aussi avec while : Exemple (deviner un nombre)
from random import randint if __name__ == "__main__":
de = randint(1, 100) while True:
a = int(input('Devinez un nombre (1-100) : ')) if a == de:
break if a < de:
print('trop petit') if a > de:
print('trop grand') print('Bravo !')
I
while True boucle ind ´efiniment ;
I
break arr ˆete les it ´erations quand le nombre est devin ´e ;
– Boucles infinies –
Si la condition de boucle est toujours vraie, et qu’il n’y a pas de break pour en sor- tir, le programme reste bloqu ´e en tournant ind ´efiniment dans la boucle !
I
Pour forcer l’arr ˆet d’un programme dans le terminal ou l’interpr ´eteur : faire Ctrl+C ;
I
Pour forcer la fermeture : faire Ctrl+D ;
– Evaluation des conditions –
I
Quel programme effectue le moins de calculs ?
# L est une liste for i in range(len(L)):
print(L[i])
# L est une liste i = 0
while i < len(L):
print(L[i]) i += 1
I
La condition du while est ´evalu ´ee `a chaque d ´ebut d’it ´eration ...
I
... et len(L) est donc appel ´ee `a chaque ´evaluation ;
I
Si len(L) ne change pas, on ´ecrira la version avec while comme ceci :
# L est une liste i = 0
n = len(L) while i < n:
print(L[i])
i += 1
– Modification d’it ´erables –
Comme len(L) n’est ´evalu ´e qu’une seule fois dans le for , on aura des probl `emes si l’on tente de modifier L :
>>> lst = [1, 2, 3]
>>> for i in range(len(lst)):
... lst.pop(i) ...
1 3
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: pop index out of range
NE MODIFIEZ JAMAIS LA TAILLE D’UN
IT ´ ERABLE SUR LEQUEL VOUS UTILISEZ
UNE BOUCLE for !
Python pas `a pas
Structures de donn ´ees en Python
– Structures de donn ´ees en Python –
I
On a d ´ej `a vu des it ´erables modifiables (list) ou non (str, tuple) ;
I
On va voir des structures plus avanc ´ees aujourd’hui ;
I
Le choix de la structure d ´ependra de vos besoins ;
I
l’ordre est-il important ?
I
veut-on autoriser les doublons ?
I
a-t-on besoin d’indices ?
I
a-t-on besoin de modifier les ´el ´ements ?
I
...
I
On verra les structures les plus utilis ´ees aujourd’hui, mais
il en existe beaucoup d’autres (voir par exemple le module
collections ) ;
Python pas `a pas
Les ensembles
– Les set –
I
Les set sont des it ´erables modifiables repr ´esentant des ensembles ; donc :
1. chaque ´el ´ement ne peut y ˆetre qu’une seule fois ; 2. il n’y a pas d’ordre, donc il n’y a pas de positions ...
3. ... et donc l’op ´erateur [] ne marche pas ;
Les ensembles sont modifiables, mais ne
peuvent contenir que des ´el ´ements non mo-
difiables.
– Utilisation des set –
I
Les set se d ´eclarent comme les listes, mais avec des accolades :
>>> S = {3, 1, 4, 6, 2}
I
Ou `a l’aide de la fonction set(iterable), aussi utile pour le transtypage :
>>> S = set([3, 1, 4, 6, 2])
>>> ensemble_vide = set()
I
Comme ce sont des it ´erables, on peut utiliser in et len
comme pour les chaˆınes, les tuples, les listes, ...
– Op ´erations ensemblistes –
I
Les op ´erations que vous connaissez sur les ensembles sont disponibles :
math python M ´ethode s ∪ t s | t s.union(t)
s ∩ t s & t s.intersection(t) s \ t s - t s.difference(t)
s∆t s ˆ t s.symmetric_difference(t)
I
Ces m ´ethodes ne modifient ni s, ni t ; si c’est votre but : Op ´eration M ´ethode
s = s | t s.update(t)
s = s & t s.intersection_update(t) s = s - t s.difference_update(t)
s = s ˆ t s.symmetric_difference_update(t)
– Autres m ´ethodes modifiant les ensembles –
I
Les autres m ´ethodes suivantes permettent de modifier les ensembles :
I
s.add(x) ajoute x `a s ;
I
s.remove(x) retire x de s si s le contient — sinon, elle provoque une erreur ;
I
s.discard(x) retire x de s sans erreur si s ne le contient pas.
I
enfin, s.pop() (sans param `etre) retire et renvoie un
´el ´ement al ´eatoire de s s’il n’est pas vide — sinon, elle
provoque une erreur.
– Comparaison d’ensembles –
I
On peut aussi comparer les ensembles `a l’aide des op ´erateurs suivants :
math python s = t s == t s 6= t s != t s ⊂ t s < t
s ⊆ t s <= t
s ⊃ t s > t
s ⊇ t s >= t
– frozenset –
I
Les frozenset sont des ensembles non-modifiables ;
I
Ils sont principalement utiles quand on veut repr ´esenter des collections d’ensembles ;
Exemple (sous-ensembles de {1, 2, 3} de taille 2)
>>> S = set([{1, 2}, {1, 3}, {2, 3}])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'
>>> S = set([frozenset([1, 2]), frozenset([1, 3]),
frozenset([2, 3])])
>>> S
{frozenset({1, 3}), frozenset({1, 2}), frozenset({2, 3})}
– Test d’efficacit ´e –
I
Autre int ´er ˆet des set : beaucoup plus rapides que les listes !
I
Dans le programme ci-dessous :
I
on cr ´ee un it ´erable S contenant {0, 1, 2, . . ., n − 1} ;
I
on cherche ensuite i dans S pour i = 0, 1, 2, . . . , n − 1 ;
I
on compare le temps total mis pour les recherches ;
$ python3 rechercheiterables.py
Temps pour 40000 recherches dans un set: 0.0019 s Temps pour 40000 recherches dans une list: 7.1033 s Temps pour 40000 recherches dans un tuple: 7.1092 s Temps pour 40000 recherches dans un frozenset: 0.0016 s
I⇒ si vous n’avez pas besoin de doublons, d’ordre ou de
positions : les set sont pr ´ef ´erables ;
Python pas `a pas
Les dictionnaires
– Dictionnaires –
I
Les dictionnaires sont comme les listes, mais : 1. les indices peuvent ˆetre autre chose que des naturels ; 2. il n’y a pas d’ordre ;
I
Ces indices sont appel ´es des cl ´es, et on leur associe des valeurs ;
I
On peut les d ´eclarer avec la syntaxe suivante :
clients = {
"Jean Dupont": "19/01/1985",
"Anne Dubois": "27/04/1966"
}
cl ´es valeurs– Dictionnaires : exemple d’utilisation –
Exemple
D = dict() # dictionnaire vide
D['toto'] = 4 # associe 4 a la cle 'toto' D['titi'] = 6
print(D['toto']) # affiche 4 D['toto'] = 'bonjour' # remplace 4 print(D['toto']) # affiche 'bonjour' print(D)
La cl ´e doit ˆetre un ´el ´ement non modifiable
– Dictionnaires : acc `es aux ´el ´ements –
I
Les m ´ethodes suivantes du dictionnaire dico permettent d’acc ´eder :
1. aux cl ´es : dico.keys() ; 2. aux valeurs : dico.values() ; 3. aux deux : dico.items() ;
Exemple
>>> dico = {"une cl´ e": "une valeur",
"une autre cl´ e": "une autre valeur"}
>>> dico.keys()
dict_keys(['une cl´ e', 'une autre cl´ e'])
>>> dico.values()
dict_values(['une valeur', 'une autre valeur'])
>>> dico.items()
dict_items([('une cl´ e', 'une valeur'),
('une autre cl´ e', 'une autre valeur')])
IComme toujours, on peut transtyper le r ´esultat ;
– Parcourir les dictionnaires –
I
On peut it ´erer sur des dictionnaires de plusieurs mani `eres : Exemple
>>> notes_etudiants = {'Jean': 0, 'Marie': 16, 'Pierre': 14}
>>> for nom in notes_etudiants.keys():
... print(nom) ...
Jean Pierre Marie
>>> for nom in notes_etudiants.keys():
... print(nom, ":", notes_etudiants[nom]) ...
Jean : 0 Pierre : 14 Marie : 16
>>> # mˆeme chose mais plus lisible:
>>> for nom, note in notes_etudiants.items():
... print(nom, ":", note) ...
Jean : 0 Pierre : 14 Marie : 16
– Ajouts et suppressions –
I
On est oblig ´e d’ajouter une cl ´e avec sa valeur, par une simple affectation : D[cle] = valeur
I
Si la cl ´e existait d ´ej `a dans D, son ancienne valeur est remplac ´ee ;
I
Pour supprimer une association, on utilise del D[cle] ;
I
Comme les dictionnaires sont des it ´erables, on peut utiliser :
1. x in D pour savoir si x est une cl ´e de D ;
2. y in D.values() pour savoir si y est une valeur de D ;
3. len(D) pour connaˆıtre le nombre de cl ´es de D ;
– Modifiables et non-modifiables –
On a vu jusqu’ici des objets de deux cat ´egories :
Types non-modifiables bool, int, float, str, tuple, frozenset
Types modifiables list, set, dict
Pour passer d’un type `a l’autre, on peut par exemple utiliser la fonction tuple() pour transformer une liste (modifiable) en un tuple (non-modifiable)
Pour les dictionnaires comme pour les listes : on a besoin des
[] pour modifier les ´el ´ements dans un for .
– Modifiables et non-modifiables –
I
Rappel : attention aux affectations d’objets modifiables !
I
Les fonctions peuvent modifier les objets modifiables, mais attention, les affectations donnent toujours des variables locales !
Exemple
def modifier(lst):
lst.append(1) # modifie lst
lst = list() # lst devient une variable LOCALE
# on perd l'acc` es au PARAMETRE lst
lst.append(1) # modifie lst LOCALE
Python pas `a pas
Slices
– Notion de slice –
I
Si t est une chaˆıne, un tuple ou une liste, t[i] donne acc `es `a son i - `eme ´el ´ement ;
I
Les slices permettent d’acc ´eder `a un intervalle de t ;
Syntaxe des slices
Si t est une liste (ou une chaˆıne, ou un tuple), t[debut:fin]
donne la sous-liste (ou la sous-chaˆıne, ou le sous-tuple) comprise entre les indices debut et fin-1.
Exemple
>>> s = 'bonjour'
>>> print(s[2:5]) 'njo'
I
Attention :
I
c’est fin-1 comme pour les range ;
I
les “mauvais indices” fonctionnent ;
– Indices n ´egatifs –
I
Python permet aussi d’utiliser des indices n ´egatifs ;
I
L’indice -i est le m ˆeme que len(t) - i (sauf pour 0) ; Exemple
0 1 2 3 4 5 6
b o n j o u r
-7 -6 -5 -4 -3 -2 -1
>>> s = 'bonjour'
>>> print(s[-2]) 'u'
>>> print(s[1:-2]) 'onjo'
I
Attention, les m ˆemes r `egles de validit ´e d’indices
s’appliquent (-10 dans une liste de 5 ´el ´ements provoque
une erreur) ;
– Param `etres par d ´efaut des slices –
I
Dans un slice, le d ´ebut et la fin ont des valeurs par d ´efaut :
I
t[:4] est la m ˆeme chose que t[0:4] ;
I
t[4:] est la m ˆeme chose que t[4:len(t)] ;
I
t[:7] d ´esigne les 7 premiers ´el ´ements ;
I
t[2:] d ´esigne tous les ´el ´ements `a partir du troisi `eme (le premier est en 0) ;
I
t[:-2] d ´esigne tous les ´el ´ements sauf les 2 derniers ;
I
t[-5:] d ´esigne les 5 derniers ´el ´ements ;
I
t[:] d ´esigne toute la liste ;
– Param `etres par d ´efaut des slices –
I
Enfin, il existe un troisi `eme param `etre qui permet comme dans les range de sp ´ecifier la taille des “sauts” :
Exemple
>>> s = "bonjour"
>>> s[::]
'bonjour'
>>> s[::1]
'bonjour'
>>> s[::2]
'bnor'
>>> s[::3]
'bjr'
– Slices et copies –
Les slices r ´ealisent des copies d’objets ou de r ´ef ´erences en m ´emoire !
I
Que l’on affecte ou non le slice iterable[i:j] `a une nouvelle variable :
I
les valeurs des ´el ´ements non modifiables de iterable[i:j] sont dupliqu ´es ;
I
les r ´ef ´erences des ´el ´ements modifiables de iterable[i:j] sont dupliqu ´es ;
I
Il faut donc bien faire attention `a la consommation en m ´emoire et aux modifications involontaires ;
[Visualisation sur PythonTutor]
– Modification de listes dans les fonctions –
I
Comme on l’a vu, lst[:] d ´esigne toute la liste ;
I
On peut l’utiliser pour modifier lst dans un appel de fonction :
Exemple (incorrect)
def effacer_liste(ma_liste):
ma_liste = list()
Exemple (correct)
def effacer_liste(ma_liste):
ma_liste[:] = list()
Python pas `a pas
It ´erables en compr ´ehension
– It ´erables en compr ´ehension –
I
L’id ´ee est d’avoir un moyen de d ´ecrire un it ´erable comme on d ´ecrit un ensemble en math ´ematiques :
E = n
2
i| i ∈ {0, 1, . . . , 10} o F = {x ∈ {1, 2, . . . , 10} | x impair}
I
La syntaxe g ´en ´erale est :
Syntaxe des compr ´ehensions
pour une liste : [expression for element in iterable]
pour un ensemble : {expression for element in iterable}
pour un dictionnaire : {cle: valeur for cle, valeur in iterable}
Si on veut autre chose, on peut transtyper la compr ´ehension.
I
N’utilisez pas les parenth `eses comme d ´elimiteurs ;
– It ´erables en compr ´ehension –
I
Utilisons les compr ´ehensions pour construire les deux ensembles donn ´es ci-dessous :
E = n
2
i| i ∈ {0, 1, . . . , 10} o F = {x ∈ {1, 2, . . . , 10} | x impair}
I
Pour le premier :
E = { 2 ** i for i in range(11)}
I
Pour le second :
F = {i for i in range(1, 11, 2)}
– Compr ´ehensions conditionnelles –
I
On peut filtrer les ´el ´ements `a rajouter `a l’aide de conditions (facultatives) :
Syntaxe des compr ´ehensions conditionnelles Comme avant :
gauche expr for element in iterable if conditions droite
o `u les conditions s’emploient comme d’habitude (voir if et while ).
I
On aurait donc pu obtenir l’ensemble des nombres impairs entre 1 et 10 comme suit :
F = {i for i in range(11) if i % 2}
– Compr ´ehensions multiples –
I
On peut utiliser plusieurs for :
C = [(i, j) for i in range(5) for j in range(4)]
I
Les for sont ´evalu ´es dans le sens de lecture, comme pour les boucles imbriqu ´ees ;
I
Ce qui pr ´ec `ede ´equivaut donc `a : Exemple
C = []
for i in range(5):
for j in range(4):
C.append((i, j))
I
Evitez de d ´epasser deux niveaux d’imbrication ; ´
– R ´ecapitulation des compr ´ehensions –
I
L = [x for x in iterable if condition] ´equivaut `a : L = []
for x in iterable:
if condition:
L.append(x)
I
S = {x for x in iterable if condition} ´equivaut `a : S = set()
for x in iterable:
if condition:
S.add(x)
I