3. Contrôle du flux d'instructions▲
Un script Python est formé d'une suite d'instructions exécutées en séquence(9) de haut en bas.
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 en utilisant des « instructions composées ».
3-1. Instructions composées▲
Pour identifier les instructions composées, Python utilise la notion d'indentation significative. Cette syntaxe, légère et visuelle, met en lumière un bloc d'instructions et permet d'améliorer grandement la présentation et donc la lisibilité des programmes sources.
Une instruction composée se compose :
- d'une ligne d'en-tête terminée par deux-points ;
- d'un bloc d'instructions indenté par rapport à la ligne d'en-tête. On utilise habituellement quatre espaces par indentation et on ne mélange pas les tabulations et les espaces.
Toutes les instructions au même niveau d'indentation appartiennent au même bloc.
Exemple :
#?Exemples?d'instruction?composée?simple
#?(les?espaces?sont?indiqués?par?un?caractère?spécifique) :
ph?=
?6.0
if
?ph?<
?7.0
:
????print
(
"C'est?un?acide."
)
if
?ph?>
?7.0
:
????print
(
"C'est?une?base."
)
#?Exemple?d'instruction?composée?imbriquée :
n?=
?3
if
?n?<=
?0
:
????print
(
'"n" est négatif ou nul'
)
else
:
????print
(
'"n" est positif'
)
????if
?n?>
?2
:
????print
(
'"n"?est?supérieur?à?2'
)
3-2. Choisir▲
3-2-1. Choisir : if - [elif] - [else]▲
Contrôler une alternative :
>>>
x =
5
>>>
if
x <
0
:
... print
(
"x est négatif"
)
... elif
x %
2
!=
0
:
... print
(
"x est positif et impair"
)
... print
(
"ce qui est bien aussi !"
)
... else
:
... print
(
"x n'est pas négatif et est pair"
)
...
x est positif et impair
ce qui est bien aussi !
Test d'une valeur booléenne :
>>>
x =
8
>>>
estPair =
(
x %
2
==
0
)
>>>
estPair
True
>>>
if
estPair: # mieux que"if estPair == True:"
... print
(
'La condition est vraie'
)
...
La condition est vraie
3-2-2. Syntaxe compacte d'une alternative▲
Pour trouver, par exemple, le minimum de deux nombres, on peut utiliser l'opérateur ternaire :
>>>
x =
4
>>>
y =
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
>>>
print
(
"Plus petit :"
, plus_petit)
Plus petit : 3
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▲
3-3-1. Notions de conteneur et d'itérable▲
De façon générale, nous parlerons de conteneur pour désigner un type de données permettant de stocker un ensemble d'autres données, en ayant ou non, suivant les types, une notion d'ordre entre ces données.
Nous parlerons aussi d'itérable pour désigner un conteneur que l'on peut parcourir élément par élément.
Pour parcourir ces conteneurs, nous nous servirons parfois de l'instruction range() qui fournit un moyen commode pour générer une liste de valeurs.
Par exemple :
Ces notions seront étudiées plus en détail au chapitre 4Conteneurs standard.
3-3-2. Python propose deux sortes de boucles▲
3-3-2-a. Répéter : while▲
Répéter une portion de code tant qu'une expression booléenne est vraie :
>>>
x, cpt =
257
, 0
>>>
sauve =
x
>>>
while
x >
1
:
... x =
x //
2
# division avec troncature
... cpt =
cpt +
1
# incrémentation
...
>>>
print
(
"Approximation de log2 de"
, sauve, ":"
, cpt)
Approximation de log2 de 257
: 8
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) :
3-3-2-b. Parcourir : for▲
Parcourir un itérable :
>>>
for
lettre in
"ciao"
:
... print
(
lettre)
...
c
i
a
o
>>>
for
x in
[2
, 'a'
, 3.14
]:
... print
(
x)
...
2
a
3.14
>>>
for
i in
range(
5
):
... print
(
i)
...
0
1
2
3
4
>>>
nb_voyelles =
0
>>>
for
lettre in
"Python est un langage tres sympa"
:
... if
lettre in
"aeiouy"
:
... nb_voyelles =
nb_voyelles +
1
...
>>>
nb_voyelles
10
3-4. Ruptures de séquences▲
3-4-1. interrompre une boucle : break▲
Sort immédiatement de la boucle for ou while en cours contenant l'instruction :
>>>
for
x in
range(
1
, 11
):
... if
x ==
5
:
... break
... print
(
x, end=
""
)
...
1
2
3
4
>>>
print
(
"Boucle interrompue pour x ="
, x)
Boucle interrompue pour x =
5
3-4-2. Court-circuiter une boucle : continue▲
Passe immédiatement à l'itération suivante de la boucle for ou while en cours contenant l'instruction ; reprend à la ligne de l'en-tête de la boucle :
>>>
for
x in
range(
1
, 11
):
... if
x ==
5
:
... continue
... print
(
x, end=
""
)
...
1
2
3
4
6
7
8
9
10
>>>
# la boucle a sauté la valeur 5
3-4-3. Utilisation avancée des boucles▲
La syntaxe complète des boucles autorise des utilisations plus rares.
3-4-3-a. 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 :
3-4-3-b. for - else▲
Un exemple avec le parcours d'une liste :
>>>
entiers =
[2
, 11
, 8
, 7
, 5
]
>>>
cible =
int(
input(
"Entrez un entier :"
))
Entrez un entier : 7
>>>
for
entier in
entiers:
... if
cible ==
entier:
... print
(
cible, 'est dans la séquence'
, entiers)
... break
# voici l'interruption !
... else
:
... print
(
cible, "n'est pas dans la séquence"
, entiers)
...
7
est dans la séquence [2
, 11
, 8
, 7
, 5
]
>>>
cible =
int(
input(
"Entrez un entier :"
))
Entrez un entier : 6
>>>
>>>
for
entier in
entiers:
... if
cible ==
entier:
... print
(
cible, 'est dans la séquence'
, entiers)
... break
# voici l'interruption !
... else
:
... print
(
cible, "est absent de la séquence"
, entiers)
...
6
est absent de la séquence [2
, 11
, 8
, 7
, 5
]
3-4-4. Traitement des erreurs : les exceptions▲
Afin de rendre les applications plus robustes, il est nécessaire de gérer les erreurs d'exécution des parties sensibles du code.
Lorsqu'une erreur se produit, elle traverse toutes les couches de code comme une bulle d'air remonte à la surface de l'eau. Si elle atteint la surface sans être interceptée par le mécanisme des exceptions, le programme s'arrête et l'erreur est affichée. Le traceback (message complet d'erreur affiché) précise l'ensemble des couches traversées.
Gérer une exception permet d'intercepter une erreur pour éviter un arrêt du programme.
Une exception sépare d'un côté la séquence d'instructions à exécuter lorsque tout se passe bien et, d'un autre côté, une ou plusieurs séquences d'instructions à exécuter en cas d'erreur.
Lorsqu'une erreur survient, un objet exception est passé au mécanisme de propagation des exceptions, et l'exécution est transférée à la séquence de traitement ad hoc.
Le mécanisme s'effectue donc en deux phases :
- la levée d'exception lors de la détection d'erreur ;
- le traitement approprié.
La séquence normale d'instructions est placée dans un bloc try.
Si une erreur est détectée (levée d'exception), elle est traitée dans le bloc except approprié (le gestionnaire d'exception).
from
math import
sin
for
x in
range(-
4
, 5
) : # -4, -3, -2, -1, 0, 1, 2, 3, 4
try
:
print
(
'{ :.3f}'
.format
(
sin
(
x)/
x), end=
""
)
except
ZeroDivisionError
: # toujours fournir un type d'exception
print
(
1.0
, end=
""
) # gère l'exception en 0
# -0.189 0.047 0.455 0.841 1.0 0.841 0.455 0.047 -0.189
Toutes les exceptions levées par Python appartiennent à un ensemble d'exceptions nommé Exception. Cette famille offre une vingtaine d'exceptions standard(10). Normalement, toutes les exceptions doivent donc être typées (munies d'un nom de type d'exception) pour éviter des erreurs silencieuses.
3-4-4-a. Syntaxe complète d'une exception :▲
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
…
else
:
… # clause exécutée en l'absence d'erreur
finally
:
… # clause toujours exécutée
L'instruction raise permet de lever volontairement une exception. On peut trouver l'instruction à tout endroit du code, pas seulement dans un bloc try :
x =
2
if
not
(
0
<=
x <=
1
) :
raise
ValueError
(
"x n'est pas dans [0 .. 1]"
)
raise, sans valeur, dans un bloc except, permet de ne pas bloquer une exception et de la propager. On peut l'utiliser pour redéclencher une erreur d'un bloc except non typé.