0% ont trouvé ce document utile (0 vote)
2 vues39 pages

Python

Le document présente les concepts fondamentaux de la programmation en Python, en expliquant la différence entre algorithmes et programmes, ainsi que le rôle des compilateurs et interpréteurs. Il aborde également les notions de variables, d'affectation, de types de données, d'expressions et d'instructions, tout en soulignant l'importance des commentaires pour la lisibilité du code. Enfin, il introduit les outils et méthodes pour interagir avec l'utilisateur et structurer des programmes complexes.

Transféré par

alamiyoussra455
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
2 vues39 pages

Python

Le document présente les concepts fondamentaux de la programmation en Python, en expliquant la différence entre algorithmes et programmes, ainsi que le rôle des compilateurs et interpréteurs. Il aborde également les notions de variables, d'affectation, de types de données, d'expressions et d'instructions, tout en soulignant l'importance des commentaires pour la lisibilité du code. Enfin, il introduit les outils et méthodes pour interagir avec l'utilisateur et structurer des programmes complexes.

Transféré par

alamiyoussra455
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

1.1.

Quelques définitions

PROGRAMMATION EN PYTHON 1. D’abord, on essaye de résoudre le problème (en s’autorisant des fautes d’orthographe, des
approximations, des abréviations, en s’aidant de schémas), comme quand on rédige le plan de
la dissertation avant de rédiger le texte final. C’est ce qu’on appelle un algorithme, etc’est
indépendant du langage de programmation choisi.

2. Ensuite, on s’occupe de rédiger la solution finale au problème, en respectant la syntaxe


exacte d’un langage. La même solution pourra ainsi être écrite dans différents langages de
1.1 Quelques définitions
programmation. C’est ce qu’on appelle un programme, il n’est compréhensible que par le
compilateur ou l’interpréteur du langage de programmation choisi, et il permet de faire
1.1.1 Programmes, compilateur et interpréteur
faire ce qui est demandé à l’ordinateur.
Les ordinateurs permettent d’automatiser des tâches. Mais ce sont des machines sans capacité
d’initiative. Un ordinateur fait ce qu’on lui dit de faire. Pour cela, il faut lui parler dans un langage On trouve des algorithmes partout dans la vie courante. Par exemple, en cuisine, un algo- rithme
qu’il "comprend". On appelle ça, un programme. s’appelle une recette. En chimie ou en biologie, un algorithme s’appelle un protocole
De façon générale, un programme est une suite d’instructions (de commandes) respectant une d’expérimentation. On peut aussi donner l’exemple qui consiste à indiquer le chemin à quelqu’un,
syntaxe précise, qui sont exécutées de façon séquentielle (c’est-à-dire les unes après les autres). Ces qui peut se faire en plusieurs langues différentes, et selon plusieurs itinéraires distincts.
instructions sont élémentaires : des affectations, des instructions conditionnelles, des répétitions Exemple : Donner l’algorithme pour faire une omelette (un seul oeuf). Préciser : les ingrédients
(itérations). nécessaires, les actions à mener (dans l’ordre).
Il existe de nombreux langages dans lesquels on peut exprimer des programmes : C, Java...
Dans la suite du cours, on utilisera un langage appelé Python. Algo Omelette_Elémentaire
Une fois que l’on a écrit un programme (c’est un texte écrit dans une syntaxe très précise), on Début
utilise un autre programme qui transforme le texte de ce programme (lisible par des humains) en {ingrédients}
un texte lisible par la machine (suite d’octets). Ce programme peut être un compilateur ou un 1 oeuf, sel poivre, beurre
interpréteur, en fonction du langage de programmation choisi. {ustensiles}
1 saladier, une fourchette, une poêle, une spatule
• Le compilateur traduit une bonne fois pour toutes un code source en un fichier indépendant
exécutable (donc utilisant du code machine ou du code d’assemblage). Par exemple C’est {procédure}
un langage compilé. Casser l’oeuf dans un saladier
Saler et poivrer
• L’interpréteur est nécessaire à chaque lancement du programme interprété, pour traduire au Battre l’oeuf à la fourchette
fur et à mesure le code source en code machine. Python est un langage interprété. Dans une poêle, faire chauffer le beurre,
Verser l’oeuf battu dans la poêle,
1.1.2 Algorithme vs Programme Cuire doucement jusqu’à l’obtention de la texture souhaitée
{baveuse à bien cuite}
Comme dit précédemment, un programme est créé pour demander à l’ordinateur de faire une Servir
suite d’actions, en général pour résoudre un problème. Le programme (=le texte) va être lu et traduit par Fin
un compilateur ou un interpréteur, qui sont eux-mêmes des programmes. Compilateurs et
interpréteurs attendent en entrée un texte sans fautes "d’orthographe" (syntax error) et qui résoutle
problème attendu. C’est parfois compliqué d’écrire directement un texte juste : qui résolve le Dans une recette de cuisine, on a généralement les ingrédients et les ustensiles nécessaires,
problème et qui soit juste syntaxiquement (= sans faute d’orthographe). Rappelez-vous vos sujets la liste des actions à mener et parfois des commentaires. On retrouve les mêmes éléments dans
de dissertations de philo, par exemple. les programmes et les algorithmes. On parle de déclarations (pour indiquer ce dont on va avoir
L’astuce quand on a un problème un peu compliqué est de travailler en 2 temps. besoin), d’instructions (les commandes) et de commentaires (informations pour l’humain qui va lire
ou relire le programme).

1.1.3 En Python
Python est un langage interprété. On disposera de deux modes d’exécution d’un code Python :

• soit on écrit un ensemble d’instructions dans un fichier puis on l’exécute

1 2
1.2. Variables, expressions, instructions 1.2. Variables, expressions, instructions

• soit on utilise l’interpréteur Python, instruction par instruction, 1.2.3 Affectation, initialisation
Affectation. Pour mémoriser une valeur dans une variable, on fait une affectation, en utilisantle
signe = (qui est ici très différent de celui utilisé en maths). Dans une affectation le membre de gauche
(identificateur) reçoit la valeur qui est à droite (qui doit d’abord être évaluée). C’est-à-direque cette
valeur (une fois calculée si nécessaire) est stockée dans cette variable.

n = 33
a = 42 + 2 * 5
1.2 Variables, expressions, instructions ch = "bonjour"
euro = 6.55957
1.2.1 Variables
Une variable est un conteneur d’information qui est identifié par son nom, c’est un endroit Initialisation. La première affectation d’une variable donnée s’appelle l’initialisation de la
pour ranger une valeur. variable. Comme son nom l’indique, la valeur d’une variable peut varier ensuite au cours de
l’exécution d’un programme. La valeur antérieure est perdue, remplacée par la nouvelle valeur.

>>> a = 3 * 7 # l’expression est évaluée, et sa valeur affectée dans a


>>> a
21
>>> b = 7.3 # le séparateur décimal est un point . et non une virgule ,
>>> b
1.2.2 Identificateur 7.3
>>> a = b + 5
Pour nommer une variable, on utilise un identificateur : c’est une suite non vide de caractères
>>> a
respectant un certain nombre de contraintes :
12.3
• Doit commencer par une lettre ou le caractère _ >>> a = a * 3 # la nouvelle valeur peut dépendre de l’ancienne valeur
>>> a
• Doit contenir seulement des lettres, des chiffres et/ou le caractère _ 36.9

• Ne doit pas être un mot-clé réservé de Python


Affectation vs comparaison. Attention : le signe “=” en Python sert seulement à faire une
Attention : les identificateurs sont sensibles à la casse, c’est-à-dire que les caractères majuscules et affectation. Si on veut savoir si deux nombres sont égaux, on utilise l’opérateur de comparaison “==”.
minuscules sont considérés comme différents (ex : ma_var ! = Ma_Var).
>>> a = 6 # initialisation de a
>>> a
Exemples : 6
>>> b = 9 # initialisation de b
• d’identificateurs valides : toto, prochaine_val, max1, MA_VALEUR, r2d2, bb8, _mavar >>> a==b # comparaison, renvoie un booléen
False
• d’identificateurs non valides : 2be, C-3PO (le tiret est considéré comme un opérateur ’moins’),
>>> a=b # affectation, a reçoit la valeur de b
ma var (l’espace sépare 2 identificateurs distincts)
>>> a # a vaut maintenant 9
9
Par convention, pour les variables en Python, on utilise des minuscules. On s’interdira également
d’utiliser des accents. On essayera de choisir des noms parlants pour faciliter la lisibilité du code.
1.2.4 Types
Les exemples ci-dessus montrent que les valeurs des variables peuvent être de plusieurs natures (ici
entier, réel, chaîne de caractères). En informatique, on parle de type. Dans de nombreux langages de
programmation, on doit déclarer le type des variables (typage statique).

3 4
1.2. Variables, expressions, instructions 1.2. Variables, expressions, instructions

Ce n’est pas le cas en Python. En Python, le typage est dynamique, c’est-à-dire que l’inter- >>> 20 // 3 # division entière
préteur déterminera automatiquement le type en fonction de la valeur qui a été affectée à une 6
variable (et il change quand la valeur de la variable change). On peut connaître ce type en écrivant : >>> 20 % 3 # reste de la division entière (modulo)
type(ma_var). Les types de base sont : entier (int), réel (float), chaîne de caractères (str) et 2
booléen (bool). >>> 2 > 8 # comparaison de 2 entiers, expression booléenne
False
>>> ’a’ < ’z’ # comparaison de 2 caractères, expression booléenne
>>> a = 17 <class ’str’> >>> a = (21==7*3) True
>>> type(a) >>> a >>> ’b’ < ’a’ # la comparaison respecte l’ordre alphabétique
<class ’int’> >>> a = 3.14 True False
>>> type(a) >>> type(a) >>> (2 <= 8) and (8 < 15) # conjonction pour comparer 3 entiers
>>> a = "salut" <class ’float’> <class ’bool’> True
>>> type(a) >>> (x % 2 == 0) or (x >= 0)
# disjonction, expr. bool. dont la valeur dépend de la
1.2.5 Expressions et opérateurs # valeur de la variable x (vrai si x pair ou positif)
>>> "a"+"b" # concaténation de chaînes de caractères
Dans les exemples, nous avons montré qu’il était possible de faire des opérations, par exemple en >>> "to"*3 # répétition de chaîne de caractères
écrivant 42 + 2 * 5. Cela s’appelle une expression, c’est une “formule” qui peut être évaluée "tototo"
(calculée). Une variable ou une constante est aussi une expression, mais dont on n’a pas besoin de
calculer la valeur (elle est déjà connue). Abréviations Quelques opérateurs permettent d’abréger les notations des affectations d’une
3*2.0 - 5 valeur dans une variable qui dépend de son ancienne valeur. Par exemple :

20 / 3 >>> a = 3 # affectation >>> a *= 3 # abrévie a = a * 3


x > 7 >>> a >>> a
3 12
Dans ces expressions, on a des opérandes, et des opérateurs. Les opérateurs que l’on peut utiliser >>> a += 1 # abrévie a = a + 1 >>> a -= 5 # abrévie a = a - 5
ne sont pas les mêmes selon le type des valeurs qu’on manipule. Quelques opérateurs : >>> a >>> a
• arithmétiques (sur des nombres, produisent des nombres) : addition +, soustraction -, 4 7

multiplication *, puissance **, division réelle /, modulo %, division entière // Priorité des opérateurs Lorsqu’une expression comporte plusieurs opérateurs, afin de savoir
dans quel ordre elle est évaluée, on considère la priorité des opérateurs. Par exemple en arithmé-
• de comparaison (sur nombres ou chaînes de caractères, produisent un résultat de type tique vous avez appris que la multiplication est plus prioritaire que l’addition, ainsi 2 ∗ 3 + 4 est
booléen) : ==, !=, <, , >, <=, >= évalué en (2 ∗ 3) + 4 = 6 + 4 = 10 et non pas en 2 ∗(3 + 4) = 2 ∗ 7 = 14.

• logiques (entre des booléens, résultat booléen) : or (disjonction), and (conjonction), not Opérateurs par ordre de priorité décroissante : • < : Inférieur
(négation). > : Supérieur
• ** : Puissance
<= : Inférieur ou égal
Exemples d’opérateurs : • * : Multiplication >= : Supérieur ou égal
/ : Division == : Égal
>>> 2 + 3 # addition // : Division entière != : Différent
5
>>> 2 * 3 # multiplication • % : Modulo
6 • in : Appartenance
• + : Addition
>>> 2 ** 3 # puissance • not : Négation booléenne
- : Soustraction
8
>>> 20 / 3 # division réelle • and : Conjonction booléenne (et)
6.666666666666667 • or : Disjonction booléenne (ou)

5 6
1.3. Outils utiles 1.4. Entrées / Sorties

l’écran (si demandé), et attend que l’utilisateur entre une donnée au clavier et la valide par un appui
Évaluation des expressions Quand des opérateurs sont de même priorité, l’expression est
sur la touche Entrée.
évaluée de gauche à droite. En cas de doute et pour améliorer la lisibilité, il est conseillé de
parenthéser les expressions pour s’assurer qu’elles soient évaluées dans l’ordre souhaité.

>>> 8 // 4 // 2 # même op., même prio., éval. de gauche à droite


1
>>> 8 // (4 // 2) # les parenthèses forcent l’éval. de droite à gauche
4
>>> 8 * 4 // 2 ** 3 # puissance évaluée en 1er, * et // de gauche à droite
4

1.2.6 Instructions
Une instruction est une action à exécuter par le programme. Un programme informatique est
constitué d’une suite d’instructions exécutées dans l’ordre pour atteindre un résultat. Par exemple,
une affectation de valeur dans une variable est une instruction. Dans la suite de ce cours nous allons
apprendre :

• des types de données plus ou moins complexes (booléens, listes, dictionnaires, fichiers)

• d’autres instructions, comme les instructions d’entrées-sorties permettant l’interaction avec


l’utilisateur du programme (lecture d’une valeur tapée au clavier, affichage d’une valeur à
l’écran : cf chapitre suivant) ;

• des structures de contrôle qui permettent d’écrire des programmes plus complexes quede
simples séquences d’instructions : exécution sélective / conditionnelle (if), répétition en
boucle (for, while).

1.2.7 Les commentaires


Les commentaires sont des annotations du programme, qui ne sont pas analysées par l’interpréteur,
mais qui servent à mieux comprendre le programme (pour vous, votre binôme, votre professeur...).
En Python les commentaires s’écrivent en commençant une ligne par # pour dire à l’interpréteur de
l’ignorer.

1.3 Entrées / Sorties

Dans la plupart des cas on a besoin de pouvoir interagir avec un programme :

• Pour lui fournir les données à traiter, en général au clavier -> entrées

• Pour pouvoir connaître le résultat d’exécution d’un programme, ou pour que le programme
puisse écrire ce qu’il attend de l’utilisateur, en général texte écrit à l’écran -> sorties

1.3.1 Les entrées

Pour gérer les entrées au clavier, on utilise la fonction input(). Quand l’ordinateur exécutela
fonction input(), il interrompt l’exécution du programme, affiche éventuellement un message à
7 8
1.4. Entrées / Sorties 1.4. Entrées / Sorties

Saisie textuelle et conversion de type. La fonction input() effectue une saisie en mode texte :la a=
valeur saisie est considérée comme une chaîne de caractères. On peut ensuite changer son type, pour 20
le convertir en nombre par exemple (attention cela ne fonctionne que si l’utilisateur a bien saisi un b=
nombre, sinon on déclenche une erreur). Cette conversion est indispensable si on veut ensuite manipuler 13
la valeur numérique. >>> print(a,end="!") # pas de retour à la ligne final
20!>>>
>>> texte = input()
>>> c = 7
123 # on suppose que l’utilisateur saisit 123 en réponse >>> print(a,b,c,sep=";",end=" !\n")
>>> texte
# séparateur ; au lieu d’espace, et on rajoute un ! avant retour chariot
’123’ # la variable texte contient la chaîne de car. ’123’ # final (qu’il faut spécifier avec \n)
>>> texte + 1 # erreur, addition chaîne + entier interdite
20;13;7!
>>> val = int(texte) # conversion de la chaîne en entier
>>>
>>> val + 1 # pas d’erreur, val est bien un entier
124
Alignement de l’affichage Il peut parfois être utile d’aligner les chaînes affichées, notamment
>>> y = int(input()) +1 # en une seule instruction
quand elles sont de tailles différentes. Par exemple imaginons qu’on veuille afficher une liste
d’entiers (colonne de gauche), leur carré (colonne du milieu), et leur cube (colonne de droite).
Message d’instructions. La fonction input() peut recevoir un paramètre optionnel indiquantle L’affichage standard avec l’instruction print(x,x**2,x**3) produira un tableau peu lisible (à
message à afficher. Il est toujours préférable de préciser un message, afin que l’utilisateur gauche ci-dessous).
comprenne pourquoi le programme s’arrête et ce qui est attendu de lui. La méthode rjust() permet de justifier l’affichage d’une chaîne de caractères à droite. Elle
>>> x = float(input("Entrez un nombre : ")) reçoit un argument qui indique la taille de la colonne dans laquelle on justifie à droite (et
Entrez un nombre : # le programme affiche le message et attend donc permet de déduire combien d’espaces il faut insérer à gauche). Ainsi l’instruction
12.3 # on suppose que l’utilisateur répond 12.3 print(str(x).rjust(2), str(x*x).rjust(3),str(x*x*x).rjust(4)) permet de jus-
>>> x + 2 tifier la première colonne (entiers à 1 ou 2 chiffres) sur 2 caractères, la 2e sur 3 caractères, et la 3e
14.3 sur 4 caractères (taille maximale de 4 chiffres). Elle produit un tableau mieux aligné et plus lisible (à
droite ci-dessous).

1.3.2 Les sorties 1 1 1 1 1 1


En mode “calculatrice”, Python lit-évalue-affiche (comme fait dans les exemples précédents) 2 4 8 2 4 8
mais quand on veut demander un affichage au sein d’un programme écrit dans un fichier (script), on 3 9 27 3 9 27
utilise la fonction print(). Elle se charge d’afficher la représentation textuelle de n’importe quel 4 16 64 4 16 64
nombre de valeurs fournies entre les parenthèses et séparées par des virgules (arguments). Par 5 25 125 5 25 125
défaut, à l’affichage, ces valeurs sont séparées par un espace et l’ensemble se termine par un retour 6 36 216 6 36 216
à la ligne. 7 49 343 7 49 343
8 64 512 8 64 512
>>> a = 20 9 81 729 9 81 729

>>> b = 13 10 100 1000 10 100 1000


>>> print("La somme de", a, "et", b, "vaut", a+b,".")

La somme de 20 et 13 vaut 33. Formatage Une autre manière de formater l’affichage consiste à utiliser l’opérateur % comme
dans les exemples ci-dessous.
Modification de l’affichage Cependant on peut modifier ce comportement par défaut (séparation par
for i in range(7,11): # répétition
des espaces et retour à la ligne final) en spécifiant les paramètres optionnels sep et/ou end. Attention,
ces paramètres fonctionnent uniquement pour la fonction print (pas avec input). On peut aussi print(’%2d’ % i,’%3d’ % i**2) # affichage de l’entier i sur 2 chiffres
insérer manuellement des sauts de ligne en utilisant "\n" et des tabulations avec "\t" # et de son carré sur 3 chiffres
; ce sont des ”caractères spéciaux”. 7 49
8 64
>>> print(a,b,sep=";") # séparateur ; mais on garde retour ligne final 9 81
20;13 10 100
>>> print("a=",a,"b=",b, sep="\n") # retour ligne entre chq arg. + final # affichage du nombre pi (fourni par le module math)
9 10
1.5. Les expressions booléennes 1.5. Les expressions booléennes

>>> print(’%1.7f’ % [Link]) # avec 1 chiffre avant la virgule et 7 après >>> (3 == 1+1) or (a>5) # op. gauche fausse donc il faut évaluer la droite
3.1415927 Traceback (most recent call last):
>>> print(’%1.17f’ % [Link]) # avec 17 chiffres après la virgule File "<stdin>", line 1, in <module>
3.14159265358979312 NameError: name ’a’ is not defined

>>> ( 2 == 1+1 ) and (a>5)


# la conjonction nécessite que les 2 opérandes soient évaluées à vrai
1.4 Les expressions booléennes Traceback (most recent call last):
File "<stdin>", line 1, in <module>
1.4.1 Définition : expression booléenne NameError: name ’a’ is not defined
Une expression qui ne peut prendre que les valeurs True (vrai) ou False (fausse) est appelée
expression booléenne. En Python, il s’agit du type bool (booléen), vu au chapitre précédent. >>> (3 == 1+1) and (a>5) # opérande gauche fausse donc conjonction aussi
False
>>> 1 < 2 < 3 # les entiers 1,2,3 sont-ils en ordre croissant strict
True 1.4.5 Abréviations des expressions booléennes
>>> 7%2 == 0 # 7 est-il multiple de 2 (reste de la division est nul)
False On peut parfois abréger certaines expressions booléennes composées (conjonctions).
>>> 2 <= 8 < 15 # comparaison de 3 entiers, expr. bool.
1.4.2 Opérateurs booléens True
>>> (2 <= 8) and (8 < 15) # conj., expr. équivalente à la précédente
OU logique : or. expr1 or expr2 vaut vrai si et seulement si au moins une des deux expres-
True
sions expr1 et expr2 est vraie, éventuellement les deux.
De telles abréviations ne sont pas toujours recommandées pour des questions de lisibilité. Par
exemple il peut être difficile d’évaluer ce que signifient les expressions suivantes. A votre avis
ET logique : and. expr1 and expr2 vaut vrai si et seulement si les deux expressions expr1 et
lesquelles sont équivalentes ?
expr2 sont vraies.
>>> 1 < 2 < 3 == 7%2 != 0
Négation logique : not. not expr vaut vrai si et seulement si expr vaut faux. >>> (1 < 2 < 3) == (7%2 != 0)
L’opérateur de négation est le plus prioritaire, suivi de and, suivi de or. Par exemple not a or >>> ((1 < 2 < 3) == 7) % 2 != 0
b and c est évalué comme (not a) or (b and c). >>> (1<2) and (2<3) and (3==1) and (1!=0)
C’est en fait la dernière expression qui correspond au détail de la première, et qui explique
1.4.3 Élément neutre des opérateurs booléens pourquoi le résultat de son évaluation est False.
On recommandera aussi de toujours bien parenthéses ses expressions booléennes, même si ce
L’élément neutre e d’un opérateur est celui tel que pour toute expression b, b OP e est égal à b.
n’est pas syntaxiquement nécessaire (revoir les priorités des opérateurs au chapitre précédent),
Pour le ET l’élément neutre est donc True, car True and b vaut toujours b.
pour les rendre plus lisibles et non ambiguës.
Pour le OU l’élément neutre est False, car False or b vaut toujours b.
>>> a or b and c # and est plus prioritaire que or
>>> a or (b and c) # équivalent à la précédente
1.4.4 Évaluation fainéante
En Python, les opérateurs and et or sont fainéants, c’est-à-dire que si l’évaluation de la >>> not a and b or c # not est plus prioritaire
première opérande permet déjà d’évaluer l’expression, alors la deuxième opérande n’est même pas >>> ((not a) and b) or c # équivalent à la précédente
évaluée.
1.4.6 Lois de De Morgan
# on suppose que la variable a n’est pas définie
>>> (2 == 1+1) or (a>=5) # opérande gauche vraie donc True Les lois de De Morgan permettent de simplifier des négations d’expressions contenant une
conjonction (and) ou une disjonction (or).
• not(expr1 or expr2) = not(expr 1) and not(expr2)

• not(expr1 and expr2) = not(expr 1) or not(expr2)

11 12
1.6. Instructions conditionnelles ’if’ 1.6. Instructions conditionnelles ’if’

Exemples d’instructions qui est exécutée. Le programme continue ensuite à l’instruction suivante. La syntaxe
not( a > 2 or b <= 4 ) équivaut à not(a>2) and not(b<=4) ce qui équivaut à ( a <= 2 ) and ( b > 4 ) not( est la suivante :
a > 2 and b <= 4 ) équivaut à not(a>2) or not(b<=4) ce qui équivaut à ( a <= 2 ) or ( b > 4 )
if condition :
suite d’instructions si vrai
1.4.7 Tables de vérité else :
Une table de vérité permet d’évaluer et de comparer des expressions booléennes. On commence suite d’instructions si faux
par lister toutes les variables et toutes les combinaisons possibles de leurs valeurs (ci-dessous
abrégées T pour True/vrai et F pour False/faux). Plus il y a de variables dans l’expression, et plus il Indentation En Python, c’est l’indentation qui détermine à quel bloc appartient une instruction.
y aura de combinaisons de valeurs possibles : pour n variables, il y a 2**n combinaisons, donc 4 Après la ligne if condition, les lignes suivantes sont indentées à droite pour signifier qu’elles
lignes pour une table de vérité à 2 variables, 8 lignes pour 3 variables, etc. appartiennent à ce bloc if. Si une instruction est alignée à gauche (au même niveau que le if), alors
Par exemple la table de vérité ci-dessous permet d’évaluer le ’ou exclusif’ (noté xor) entre 2 elle marque la fin de l’instruction conditionnelle. Pensez donc toujours à bien indenter votre code
variables a et b, défini comme ’soit a soit b est vraie’ (a or b) ’mais pas les 2 en même temps’ (not (ce qui le rend aussi beaucoup plus lisible).
(a and b)).
Exemple
a b a or b a and b not (a and b) a xor b
V V V V F F x = 5
V F V F V V if x > 0 :
F V V F V V print(x, "est plus grand que 0") # dans le bloc if
F F F F V F print("il est strictement positif") # dans le bloc if
else : # sinon (donc si condition fausse)
TABlE 1.1 – Table de vérité pour le ou exclusif print(x, "est négatif ou nul") # dans le bloc else
print("Fin") # ni dans if ni dans else, toujours exécutée,
# après la fin de l’instruction conditionnelle
1.5 Instructions conditionnelles ’if’ Attention, on peut avoir un if sans else, mais pas l’inverse. Si on ne veut faire aucun
traitement quand la condition est fausse, alors il ne faut pas écrire de else. On ne peut en aucun
En programmation, on peut vouloir effectuer des actions différentes selon qu’une certaine condi- cas écrire un bloc else vide ! Si on ne veut exécuter une instruction que quand la condition est
tion est remplie ou pas. Par exemple : faire un traitement différent selon que la valeur d’une variable fausse, il faut écrire un if avec la négation de cette condition.
est positive ou non.

1.5.3 Cas multiples


1.5.1 Syntaxe basique
Pour enchaîner les conditions, on dispose également du mot clé elif (contraction de else if). Les
L’instruction conditionnelle la plus simple en Python s’écrit comme ceci : parties elif sont optionnelles, comme la partie else. On peut mettre plusieurs blocs elif pour
distinguer autant de conditions que nécessaire. Par contre il ne peut y avoir qu’un seul else (cas
if condition :
par défaut), qui signifie que toutes les conditions précédentes sont fausses.
suite d’instructions si vrai

Dans ce cas, si la condition est vraie, la suite d’instructions est exécutées. Si la condition est fausse, Remarque : la condition d’un bloc elif n’est évaluée que si les conditions précédentes ont échoué.
rien n’est fait, le programme continue après cette instruction. La condition doit être une expression Le programme ne pourra rentrer que dans un seul bloc d’une instruction conditionnelle (le premier
booléenne (par exemple le résultat d’une comparaison entre deux nombres, etc). dont la condition est vraie). Il n’est donc pas nécessaire de spécifier la négation des conditions
Attention à l’indentation, c’est-à-dire le décalage à droite et l’alignement de la suite d’ins- précédentes dans les conditions suivantes. Par exemple :
tructions à l’intérieur du if. C’est l’indentation qui détermine dans quel bloc se trouve une
instruction, et qui indique donc dans quel cas elle doit être exécutée. note = int(input("Quelle est votre note en maths ?"))

# ce qu’il ne faut pas faire


1.5.2 Syntaxe si-alors-sinon
if note<10:
Si on veut faire quelque chose quand une condition est vraie, et autre chose quand elle est print("Vous n’avez pas la moyenne")
fausse, on peut rajouter un bloc else (sinon). Dans ce cas, si la condition est vraie, la première # on teste inutilement si note>=10
suite d’instructions est exécutée, alors que si la condition est fausse, c’est la deuxième suite elif 10<=note<12:

13 14
1.6. Instructions conditionnelles ’if’ 1.6. Instructions conditionnelles ’if’

print("Pas mal...") print("Une seule racine reelle")


# on teste inutilement si note>=12 else : # ici on a forcement d < 0
elif 12<=note<15: print("Aucune racine reelle")
print("Mention Bien !")
Attention : les elif sont suivis d’une condition, par contre le else n’est pas suivi d’une
# on teste inutilement si note>=15
condition. Il correspond exactement à la négation de la condition du if, ou à la négation du
elif note>=15:
if et de tous les elif précédents : on y rentre par défaut si on n’a pu rentrer dans aucun bloc
print("Vous avez la bosse des maths !")
précédent de l’instruction conditionnelle.

# la version correcte
1.5.5 Imbrication
if note < 10:
print("Vous n’avez pas la moyenne") Remarque : on peut imbriquer les instructions conditionnelles, c’est-à-dire écrire un if dans
# si le premier test échoue, on sait déjà que note>=10 le bloc d’instructions d’un autre if. Cela permet de distinguer des sous-cas, par exemple une fois
# on n’a donc pas besoin de le vérifier dans la condition du elif que je sais que ma variable est positive, je peux vouloir distinguer les valeurs paires ou impaires.
elif note < 12: Attention à l’indentation. A chaque nouveau bloc imbriqué dans le précédent, on décale d’un
print("Pas mal...") cran supplémentaire vers la droite.
elif note < 15:
print("Mention Bien !") Exemple
# si les 2e et 3e tests échouent aussi, on sait que note >= 15, else suffit
print("Testeur de parite")
else:
x = int(input("Entre un entier positif"))
print("Vous avez la bosse des maths !")
if x>=0 : # x est positif
if x%2==0 : # x est positif ET pair
1.5.4 Cas par défaut print(x,"est pair")
Attention : en l’absence d’un bloc else (cas par défaut) il est possible que le programme ne rentre else : # x est positif ET non pair (donc impair)
dans aucun des blocs d’une instruction conditionnelle (si toutes les conditions sont fausses).Il est print(x,"est impair")
donc en général préférable de toujours prévoir un cas par défaut (bloc else). Par exemple : else : # x n’est pas positif (donc negatif)
print("Erreur !",x,"est negatif")
reponse = input("Faites-vous du sport régulièrement ? (oui/non) ")
if reponse==’oui’: 1.5.6 Nombres aléatoires
print("Super, c’est bon pour la santé !")
elif reponse==’non’: Le module random permet de générer des nombres pseudo-aléatoires. Il fournit par exemple
print("Dommage, vous devriez vous y mettre...") les fonctions suivantes qui seront utilisées en TD et TP :
# en l’absence d’un bloc else, le programme n’affichera rien • randint(a,b) : renvoie un entier pseudo-aléatoire entre les bornes a et b (incluses).
# si l’utilisateur répond autrement que par ’oui’ ou ’non’
• randrange(a,b,step) : renvoie un entier pseudo-aléatoire dans range(a,b,step), ce
# il faut rajouter un cas par défaut pour gérer les exceptions
qui permet en plus de spécifier un pas (par défaut 1). Attention la borne supérieure b est ici exclue.
else:
print("Je n’ai pas compris la réponse") • random() : renvoie un réel pseudo-aléatoire entre 0 et 1.
• choice(l) : renvoie un élément au hasard parmi ceux de la liste l.
Exemple : calculer le nombre de racines réelles d’un polynôme du second degré. On sait qu’il ya
3 cas selon que le déterminant est strictement positif, nul, ou strictement négatif. Pour utiliser les fonctions de ce module, il faut l’importer au début du programme avec la commande
: import random puis préfixer les appels aux fonctions par le nom du module. Exemple :
a = 3.2 # coefficient du monome de degre 2 import random
b = 5 # coefficient du monome de degre 1 # nombre entier au hasard entre 1 et 10
c = -7.9 # coefficient du monome de degre 0 i = [Link](1,10)
d = b**2 - 4*a*c # nombre réel au hasard entre 0 et 20
if d>0 : x = 20 * [Link]()
print("Deux racines reelles distinctes")
elif d==0 :

15 16
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

1.6 La boucle conditionnelle ’while’ Ce programme fonctionne correctement, mais si l’utilisateur entre une valeur B nulle, il n’a
pas de deuxième chance. Comment le modifier afin qu’il continue de demander la valeur de B à
Précédemment, nous avons appris à utiliser les instructions conditionnelles (if-elif-else), l’utilisateur, jusqu’à ce que celle-ci ne soit pas égale à 0 ?
qui permettent d’exécuter une suite d’instructions uniquement si une certaine condition est On pourrait répéter manuellement le même code un certain nombre de fois. Par exemple, pour
vérifiée. On appelle ces instructions des structures de contrôle. En programmation, il existe d’autres donner à l’utilisateur 3 chances d’entrer une valeur correcte, on peut naïvement écrire :
structures de contrôle, les boucles (ou itérations), qui permettent de répéter un ensemble
d’instructions plusieurs fois. En particulier la boucle while permet de répéter un bloc d’instructions a = int(input(‘Donnez la valeur de A : ‘))
tant que une certaine condition (une expression booléenne) reste vraie. On appelle donc cette b = int(input(‘Donnez la valeur de B : ’))
structure une boucle conditionnelle. Comme pour le if, c’est l’indentation des instructions qui if b == 0 :
détermine si elles sont dans la boucle (exécutées tant que la condition est vraie) ou en dehors b = int(input(‘B ne peut etre nul, veuillez reessayer : ’))
(exécutées après la fin de la boucle, quand la condition devient fausse). En Python, la syntaxe if b == 0 :
générale du while est la suivante : b = int(input(‘B ne peut etre nul, veuillez reessayer : ’))
if b == 0 :
while condition :
instruction_1 b = int(input(‘B ne peut etre nul, veuillez reessayer : ’))
instruction_2 if b != 0 :
... print(‘A / B = ‘, a // b)
instruction_n else:
# ici la condition est fausse, on sort de la boucle print(‘Division par 0 impossible’)

Cependant, ce code est très répétitif (ce qui n’est pas bon !) et ne permet de répéter cette action qu’un
Condition de boucle : si la condition est fausse dès le premier essai, alors on n’entre jamais dans nombre limité de fois (ici 3 fois). Ce n’est pas le résultat souhaité. A l’aide du while, onpeut simplement
la boucle et on passe directement à la suite du programme. Au contraire, si la condition reste ré-exprimer le programme comme suit :
toujours vraie, alors on ne sort jamais de la boucle, le programme ne se termine pas, on est coincé
dans une boucle infinie : attention danger ! Pour interrompre un programme qui boucle, il faut a = int(input(‘Donnez la valeur de A : ‘))
taper Ctrl-C au clavier pendant l’exécution. b = int(input(‘Donnez la valeur de B : ’))
while b == 0 :
Utilité : les boucles sont très utiles dans plusieurs cas : pour filtrer les entrées de l’utilisateur ; pour b = int(input(‘B ne peut etre nul, veuillez reessayer : ’))
rejouer un programme ; pour répéter plusieurs fois les mêmes instructions. # sortie de la boucle quand b est different de 0
# maintenant on peut faire la division sans erreur
1.6.1 While pour filtrer print(‘A / B = ‘, a // b)

On a vu qu’un programme pouvait interagir avec l’utilisateur en lui demandant d’entrer des Ce programme redemande la valeur de B tant que celle-ci est égale à 0 (c’est-à-dire jusqu’à ce
valeurs. On a parfois besoin de vérifier que les valeurs entrées par l’utilisateur respectent bien
qu’elle soit non nulle). Si on sort de la boucle, cela veut dire que b n’est plus égal à 0, et on peut alors
certains critères, sous peine que le programme ne fonctionne pas correctement : c’est ce qu’on
effectuer notre division sans re-vérifier sa valeur.
appelle filtrer les entrées.
Ce type de comportement est observé très souvent dans les programmes que nous utilisons
tous les jours. Par exemple, un programme qui nous demande de nous identifier avec un mot de
1.6.2 While pour rejouer un programme
passe (par exemple : Skype), va continuer à afficher la page d’accueil tant qu’on n’a pas rentré les La boucle while peut aussi être utilisée pour répéter un programme un nombre indéterminé de
bons identifiants. fois, selon le choix de l’utilisateur. Par exemple voici un programme qui demande à l’utilisateur un
Considérons un exemple simple, qui demande à l’utilisateur deux entiers positifs A et B, et caractère et affiche son code ASCII.
affiche le quotient de la division de A par B. Pour avoir un résultat correct, nous devons d’abord
vérifier que B est différent de 0. Le programme peut être exprimé de la façon suivante : carac = input("Entre un caractere ?")
code = ord(carac)
a = int(input(‘Donnez la valeur de A : ‘))
print("Le code ASCII de",carac,"est",code)
b = int(input(‘Donnez la valeur de B : ’))
if b != 0 : Si on veut maintenant proposer à l’utilisateur de recommencer avec un nouveau caractère, puis un
print(‘A / B = ‘, a // b) # division entière autre, etc, jusqu’à ce qu’il demande d’arrêter, on peut compléter le programme comme ceci :
else:
print(‘Division par 0 impossible’) play = ’oui’ # on initialise à ’oui’ pour jouer au moins une fois

17 18
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

while play==’oui’ : 1.6.4 Accumulateurs et drapeaux


carac = input("Entre un caractere ?")
Lorsqu’on parcourt un ensemble de valeurs, il arrive souvent qu’on ait besoin de garder en
code = ord(carac)
mémoire certaines informations sur les valeurs parcourues. Par exemple, on peut avoir besoin de
print("Le code ASCII de",carac,"est",code)
calculer la somme ou le produit de ces valeurs. Ou encore, on pourrait avoir besoin de garder
play = input("veux-tu rejouer ? oui/non ")
en mémoire la plus grande ou la plus petite valeur que nous ayons rencontrée dans une liste de
# sortie de boucle si l’utilisateur répond autre chose que ’oui’
valeurs. Ceci introduit la notion de variable accumulateur.
print("Fin du programme")

Ce programme rentre au moins une fois dans la boucle puisqu’on initialise la variable play à Accumulateurs
la valeur ’oui’, donc le premier test de la condition réussit. Ensuite, après chaque exécution, le
Prenons l’exemple du calcul d’une somme d’entiers. On veut écrire un programme qui calcule et
programme demande à l’utilisateur de dire s’il veut continuer ou pas. Tant que l’utilisateur répond
affiche la somme des 10 premiers entiers strictement positifs (1 à 10). Comme dans l’exemple
’oui’, le programme recommence en demandant un nouveau caractère. Dès que l’utilisateur répond
précédent, nous avons besoin d’une variable compteur (qu’on appellera i), qui va compter de 1 à
’non’ (ou toute autre chaîne que ’oui’) la boucle se termine, et l’instruction suivante est exécutée
10. De plus, nous aurons besoin d’une variable accumulateur (qu’on appellera ‘somme’), qui va
(affichage du message de fin).
accumuler progressivement la somme de toutes les valeurs de i que l’on rencontre. Généralement,
on initialise l’accumulateur à l’élément neutre de l’opération que l’on veut effectuer. Dans notre
1.6.3 While pour répéter, compteur de boucle exemple, l’accumulateur a été initialisé à 0 car c’est l’élément neutre de l’addition (0+x=0).
La boucle while peut également être utilisée pour répéter un bout de code un nombre déterminé
i = 1
de fois. Pour ce faire, on utilise une variable compteur qui s’incrémente à chaque itération. Par
somme = 0 # initialement, la somme est égale à 0
exemple, si on voulait afficher les 10 premières puissances de 2, on pourrait le faire de la manière
while i <= 10 :
suivante :
somme = somme + i # chq valeur de i est ajoutée à somme (accumulation)
i = 0 # notre variable compteur i = i + 1 # ne jamais oublier de mettre à jour le compteur
while i < 10 : # pour 10 valeurs de i, entre 0 et 9 # affichage une seule fois, après la fin de la boucle
print( 2 ** i ) # afficher 2 puissance i print(‘La somme des 10 premiers entiers est : ‘, somme)
i = i + 1 # incrémenter compteur à chaque itération
Drapeaux
Ici, la valeur du compteur i augmente de 1 (on dit que la variable i a été incrémentée) après chaque
affichage. Le premier affichage est effectué lorsque i est égal à 0, puis tout de suite après i est Parfois, l’information qu’on souhaite garder sur notre séquence n’est pas une valeur numérique
incrémenté et prend la valeur 1. Puisque i est toujours inférieur à 10, la boucle continue et l’affichage est mais une propriété. Par exemple, est-ce que tous les nombres parcourus sont impairs ? Dans ce cas,
encore effectué pour i = 1, etc. L’affichage continue donc jusqu’à ce que i devienne supérieur ou égal on peut utiliser une variable booléenne qui est égale à True si la propriété est vérifiée, et à False dans
à 10. En d’autres mots, la variable i va compter de 0 à 9. le cas où cette propriété est fausse. Cette variable, un accumulateur booléen, est aussi appelée
Attention : si on oublie d’incrémenter le compteur, il ne deviendra jamais supérieur ou égal à "drapeau" (ou flag).
10, et la boucle ne s’arrêtera jamais, c’est une boucle infinie (mauvais !).
Il est également possible de compter avec un pas différent de 1. Par exemple, le programme suivant Exemple : on veut lire 10 entiers et vérifier qu’ils sont tous impairs. Pour que cette propriété soit
avance par pas de 2 afin d’afficher tous les entiers positifs pairs inférieurs à 100. vraie, il faut que tous les nombres lus soient impairs. Autrement dit, il faut que : premier nombre est
impair ET deuxieme nombre est impair ET ... Il s’agit donc d’une accumulation utilisant
i = 0
l’opérateur ET (and).
while i < 100 :
Dans cet exemple, la drapeau tous_impairs est initialisé à True, car c’est l’élément neutre de
print(i)
l’opération "and" : si au moins un élément est pair, le drapeau sera égal à False, sinon il restera à
i = i + 2
True. Si le drapeau était une disjonction, c’est-à-dire qu’on utilise un opérateur OU (or) entre les
Le pas peut également être négatif : on parcourt en ordre décroissant. Dans ce cas on initialise le éléments accumulés, alors l’élément neutre serait False : en effet il suffit que l’une des valeurs soit
compteur à la valeur supérieure, et on précise la borne inférieure comme condition de boucle. Par vraie pour que la disjonction soit vraie.
exemple, pour afficher les 10 premiers entiers strictement positifs dans l’ordre décroissant :
i=0
i = 10 # borne supérieure tous_impairs = True
while i > 0 : # condition sur la borne inférieure while i < 10:
print(i) x = int(input(’Entrez un entier:’))
i = i – 1 # décrémenter le compteur tous_impairs = tous_impairs and x % 2 != 0

19 20
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

i = i + 1 Instruction Break
if tous_impairs:
L’instruction break permet de sortir d’une boucle immédiatement, indépendamment de la condition
print(’Tous les nombres entrés sont impairs’)
du ’while’. Cependant le plus souvent son utilisation n’est pas nécessaire. Par exemple la boucle
else:
suivante se terminera dès que i est égal à 2, et donc n’affichera que les valeurs 0 et 1. Mais il aurait
print(’Au moins un nombre entré n’était pas impair’)
mieux valu changer la condition du while en i<2.
Lorsqu’on utilise l’opérateur ’and’, il suffit que l’une des valeurs ne soit pas impaire pour que

notre drapeau soit faux. Une manière équivalente et plus intuitive d’écrire ce type de programme # avec break # version correcte sans break
est donc de mettre le booléen tous_impairs a False dès qu’on tombe sur une valeur paire. i = 0 i=0
while i < 10: while i<2:
i=0 if i == 2: print(i)
tous_impairs = True break i+=1
while i < 10: print(i)
x = int(input(’Entrez un entier:’)) i = i + 1
if x % 2 == 0:

instructions n’ont pas toujours d’équivalent dans les autres langages de programmation. On essaiera donc autant
tous_impairs = False
que possible d’éviter d’utiliser break et continue.
i = i + 1
if tous_impairs:
print(’Tous les nombres entrés sont impairs’)
else:
print(’Au moins un nombre entré n’était pas impair’)

1.6.5 Boucle infinie, Break, Continue


Boucle infinie

Une boucle peut s’exécuter indéfiniment lorsque la condition du while est toujours vérifiée
(i.e. ne devient jamais fausse). Cela peut être intentionnel, par exemple en utilisant comme
condition le booléen True. Le programme suivant continue à afficher tout ce que l’utilisateur rentre
au clavier, et ne s’arrête jamais.

while True:
a = input()
print(a)

Mais il arrive également qu’on rentre dans une boucle infinie par erreur, parce qu’on oublie de
mettre à jour les compteurs de boucle. Dans l’exemple suivant on oublie d’incrémenter la valeur de
i, ce qui fait que la condition i < 10 reste tout le temps vraie. Le programme va donc afficher 1 (2 à
la puissance 0) à l’infini, jusqu’à être interrompu par l’utilisateur avec Ctrl-C.

i = 0
while i < 10:
print(2 ** i)

Altération du fonctionnement de la boucle - Inconvénients

Les instructions break et continue permettent d’altérer le comportement normal de la boucle


while. Cependant, leur utilisation rend le code plus difficile à lire et analyser, en particulier s’il contient
plusieurs niveaux d’imbrications et/ou de longues instructions dans le while. De plus ces
21 22
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’
Une autre utilisation typique de ’break’ consiste à éviter les expressions booléennes
compli- quées. Par exemple, supposons qu’on veuille lire des entiers au clavier jusqu’à ce
qu’on tombe sur un multiple de 2, 3, 5, 7, 11, ou 13. On peut écrire une longue condition
booléenne, ou bien la séparer en plusieurs lignes en utilisant ’break’

# version 1: longue condition


booléenne a = int(input("Tape un
entier"))
while a%2!=0 and a%3!=0 and a%5!=0 and a%7!=0 and a%11!=0 and
a%13!=0: a = int(input("Retape un entier"))

# version 2: avec break, on teste chaque sous-condition à tour


de rôle a = int(input())
while True:
if a % 2 ==
0:
break
if a % 3 ==
0:
break
if a % 5 ==
0:
break
if a % 7 ==
0:
break
if a % 11
== 0:
break
if a % 13
== 0:
break
a = int(input())

Dans certains cas, break peut aussi être utilisé pour éviter la répétition de code. Par
exemple, supposons que l’on veuille écrire un programme qui lit trois nombres au clavier,
et qui continue à afficher la moyenne des trois nombres jusqu’à ce que cette moyenne soit
inférieure à 10.

21 22
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

# version 1 : répétition de code # version 2 : break évite la répétition Instruction Continue


a = int(input()) while True:
Comme break, l’instruction continue permet d’altérer le comportement normal de la boucle.
b = int(input()) a = int(input())
continue permet de passer directement à l’itération suivante de la boucle en ignorant toutes les
c = int(input()) b = int(input())
instructions qui restent dans l’itération courante. Par exemple, le programme suivant affiche la
moyenne = (a + b + c) / 3 c = int(input())
somme des 10 premiers nombres entrés au clavier qui ne sont pas multiples de 2 ni de 3. Dans la première
while moyenne >= 10.: moyenne = (a + b + c) / 3
version avec continue, lorsque la condition du if est vérifiée, on repasse directement au début de la
print(moyenne) # dès que moyenne<10 sortie de la bcle
boucle pour lire un autre nombre, sans changer la somme, et sans incrémenter i. Dans la 2e version,
a = int(input()) if moyenne < 10:
on teste si la condition est fausse avant de comptabiliser n, ce qui donnera le même résultat.
b = int(input()) break
c = int(input()) print(moyenne)

moyenne = (a + b + c) / 3 # version avec instr. continue # réécriture sans instr. continue


i = 0 i=0
Comment remplacer break A noter que l’on essaiera de se passer de l’utilisation de break dansla somme = 0 # initialisation somme somme=0
mesure du possible car cela peut rendre le programme difficile à lire et à comprendre. Une autre astuce while i < 10: while i<10:
qui permet d’éviter le cas précédent sans utiliser break est d’initialiser la condition n = int(input()) n=int(input())

de la boucle de sorte à être sûr d’y rentrer une première fois. On préférera cette solution à celle # si n est un multiple de 2 ou de 3 # on utilise la nég. de la cond.
utilisant break. if n % 2 == 0 or n % 3 == 0: # si n mult. ni de 2 ni de 3
# passer à l’itérat. suivante if n%2!=0 and n%3!=0:
moyenne = 100 # On initialise à une moyenne >= 10 pour être sûr
continue # on l’ajoute à la somme
# qu’on rentre dans la boucle une première fois
# donc ici n mult. ni de 2 ni de 3 somme += n
while moyenne >= 10:
somme = somme + n i += 1
a = int(input())
i = i + 1
b = int(input())
c = int(input())
moyenne = (a + b + c) / 3 1.6.6 Imbrication de boucles

if moyenne >= 10: Il peut y avoir une boucle while parmi les instructions dans un bloc while : on parle alors
print(moyenne) de boucles imbriquées. Prenons comme exemple le programme ci-dessous. Ici, i est le compteur
On peut utiliser le caractère \ pour séparer une expression booléenne trop longue en plusieurs de boucle de la première boucle while (boucle externe) et j celui de la deuxième boucle while
lignes : (boucle interne). (Attention les 2 compteurs doivent être des variables différentes !) La boucle
externe ne passe à l’itération suivante (prochaine valeur de i), qu’après que la boucle interne a fini
a = int(input()) toutes ses itérations. Dans l’exemple, pour chaque valeur de i (de 1 à 3), j comptera de 1 à 2.
while a % 2 != 0 and \

a % 3 != 0 and \ # exemple de programme # affichage produit


a % 5 != 0 and \ i = 1 1, 1
a % 7 != 0 and \ while i <= 3: 1, 2
a % 11 != 0 and \ j = 1 2, 1
a % 13 != 0: while j <= 2: 2, 2
a = int(input()) print(i, ", ", j) 3, 1

j = j + 1 3, 2
Enfin pour les conditions d’arrêt de boucle, on préférera les intégrer directement dans la condition i = i + 1
de la boucle.
23 24
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

if condstop :
# version avec break (à ÉVITER) break # réécriture sans break (à PRÉFÉRER)stop=False
while cond: # on teste les 2 conditions while (not condstop) and cond:
instructions instructions

23 24
1.7. La boucle conditionnelle ’while’ 1.7. La boucle conditionnelle ’while’

Exemple d’application : le
programme ci-dessous demande à
l’utilisateur un entier N et affiche
un carré de caractères ’*’ de N
lignes et N colonnes.

N = int(input("Entrez la
valeur de N: "))
i =
0

# compteur de lignes
while i <
N:

# N lignes
j =
0

# compteur d’étoiles
par ligne

23 24
1.8. Les fonctions 1.8. Les fonctions

while j < N: # N étoiles par ligne


print(’*’, end="") # pas de retour chariot, étoiles sur même ligne
j = j + 1 # passage a l’étoile suivante
# fin de l’itération sur j qui a affiché N étoiles
print() # maintenant, saut de ligne
i = i + 1 # on passe à la ligne suivante
# fin de l’itération sur i qui a affiché N lignes

Exercice d’application Modifier ce programme pour afficher un rectangle de N lignes et M


colonnes. Exemple : fonction géométrique de calcul de distance entre 2 points

1.7 Les fonctions


On a pour l’instant développé uniquement des programmes tout-en-un. Les fonctions permettent de
découper le code en plusieurs morceaux réutilisables. Le but des fonctions est de structurerson
code lorsque l’on fait plusieurs fois la même chose (ou presque) :

• Pour qu’il soit plus lisible (plusieurs morceaux)

• Pour qu’il soit plus facilement modifiable (pas de duplication de code)

• Pour qu’il soit plus facile à tester (tester chaque morceau séparément)
Voici le code de cette fonction, qui est à définir au-dessus de votre programme principal. Cette
fonction reçoit 4 arguments : absA, ordA, absB, ordB. Elle renvoie 1 valeur de retour de type
Un exemple du TP
float. Elle n’a pas d’effets de bord (en particulier elle n’affiche rien).
import turtle
def distance(absA, ordA, absB, ordB) :
# fonction qui trace un carre de taille egale a cote
d=(absB-absA)**2 + (ordB-ordA)**2
def carre(cote) :
d=d**(1/2)
i = 1 # compteur du nb de cotes
return d
while i <= 4 :
[Link](cote) On peut alors écrire le programme principal suivant, qui appelle cette fonction en lui passant 4
[Link](90) valeurs pour ses 4 paramètres (dans le même ordre) :
i=i+1
# programme principal # prog. principal
carre(100) # carre de taille 100 print(distance(1, 2, 1, 5))
[Link]() xA=2
[Link](130) yA=3
[Link]() z=distance(xA, yA, 0, 0)
print("Distance de (0,0) à A :", z)
carre(50) # carre de taille 50
On remarque que les valeurs passées en paramètres peuvent être soit des constantes (les entiers 1,
2, 1, 5 dans le premier appel), soit des variables (les variables xA,yA dans le deuxième appel).
1.7.1 Principe d’une fonction On remarque aussi que les variables n’ont absolument pas besoin d’avoir le même nom que celui
Une fonction est une suite d’instructions, encapsulées dans une «boîte», identifiée par un nom ; elle utilisé dans la définition de la fonction. C’est l’ordre qui compte : la première valeur (constante
reçoit zéro, un ou des arguments / paramètres ; elle renvoie zéro, une ou plusieurs valeurs de ou variable) est affectée au premier argument, la 2e valeur au 2e argument, etc. Il faut donc
retour ; et elle crée éventuellement des effets de bord modifiant l’environnement (interactions passer exactement autant de valeurs lors de l’appel que le nombre de paramètres défini pour cette
entrées/sorties, turtle, etc). On peut appeler cette fonction dans un programme pour réutiliser ces fonction.
instructions plusieurs fois, sur des paramètres différents. Cette fonction renvoie une valeur, quand on l’appelle il faut donc faire quelque chose de cette
valeur : soit on l’affiche directement (comme dans le premier appel), mais alors on ne pourra

25 26
1.8. Les fonctions 1.8. Les fonctions

plus réutiliser cette valeur ; soit on la stocke dans une variable (ici dans la variable z pour le 2e 1.7.3 Appel d’une fonction
appel). Attention, la fonction renvoie une valeur, qui est stockée dans la variable d dans le corps de Syntaxe Une fois définie, on peut appeler une fonction par son nom :
la fonction, mais cette variable d est locale à la fonction, elle n’existe pas dans le programme
• Depuis le programme principal
principal. Il faut donc affecter la valeur de retour dans une nouvelle variable, définie dans le
programme principal ou dans la fonction appelante. • Depuis une autre fonction
• Directement depuis l’interpréteur

On peut aussi appeler cette fonction directement depuis l’interpréteur. On peut appeler soit des fonctions qu’on a soi-même définies, soit des fonctions déjà fournies par Python ou par
ses nombreuses librairies (à condition de les avoir importées avant avec import). On a par exemple déjà utilisé des
>>> distance(0, 1, 3, 5) fonctions des modules turtle et random.
La syntaxe pour appeler une fonction est la suivante :
5.0
>>> distance(1,2,4,7) nom_fonction(argument1, argument2, ...)
5.830951894845301
Passage des paramètres Lors de l’appel d’une fonction, les parenthèses doivent contenir exactement autant de
valeurs (constantes ou variables) que la fonction a d’arguments. Ces valeurs sont affectées aux paramètres dans le
1.7.2 Définition d’une fonction même ordre. Si la fonction n’a aucun paramètre, les parenthèses sont vides.
Si on appelle une fonction en lui passant trop de valeurs ou pas assez (par rapport à son nombre de paramètres),
La syntaxe pour définir une nouvelle fonction est la suivante : on déclenche une erreur. Par exemple avec la fonction distance définie ci-dessus avec 4 paramètres :

def nom_fonction(argument1, ..., argumentN) : >>> distance(1, 2)


Traceback (most recent call last):
instructions à exécuter
File "<stdin>", line 1, in <module>
return valeur de retour TypeError: distance() missing 2 required positional arguments: ’absB’ and ’ordB’

>>> distance(1,2,3,4,5)
Note : le return est facultatif (dans ce cas la fonction ne renvoie rien), ainsi que les arguments
Traceback (most recent call last):
/ paramètres (une fonction peut ne recevoir aucun paramètre), mais pas les parenthèses (qui sont File "<stdin>", line 1, in <module>
alors vides). TypeError: distance() takes 4 positional arguments but 5 were given

Appel d’une fonction sans paramètres Pour appeler une fonction sans paramètres, il faut quand même
Définition d’une fonction sans paramètres
utiliser des parenthèses (mais vides) pour indiquer qu’on veut exécuter cette fonction. Par exemple avec la fonction
bonjour() définie ci-dessus, directement dans l’interpréteur :
Voici un exemple de fonction sans paramètre (on note qu’il y a des parenthèses vides après le
>>> bonjour()
nom de la fonction, ces parenthèses sont obligatoires). Cette fonction n’a aucune valeur de retour
bonjour
(pas de return), par contre elle a un effet de bord, l’affichage d’un message à l’écran. >>> bonjour
<function bonjour at 0x1048c3048>
def bonjour() :
print("bonjour") Valeur de retour Si une fonction renvoie une valeur de retour, il faut soit utiliser cette valeur immédiatement, ou
l’enregistrer dans une variable pour pouvoir s’en resservir plus tard. Si on se contente d’appeler la fonction, la valeur
Ci-dessous, la fonction n’a pas de paramètre, elle a un effet de bord (affichage du message ’Quel est perdue.
est ton nom ?’ et attente d’une saisie par l’utilisateur), et elle renvoie une valeur.
# definition d’une fonction addition
def addition(x,y):
def demander_nom():
s = x+y
nom=input("Quel est ton nom? ") return s
return nom
# appel de la fonction depuis l’interpréteur
La fonction suivante n’a ni paramètre ni valeur de retour, mais a des effets de bord (dessine un carré >>> addition(3,4) # calcule la somme mais ne sauve pas le résultat
dans la fenêtre turtle). >>> print(s) # s est une variable locale à la fonction
# elle est inconnue ici !
import turtle Traceback (most recent call last):
def carre_standard(): File "<stdin>", line 1, in <module>
i = 1 # compteur du nombre de cotes NameError: name ’d’ is not defined
while i <= 4 :
[Link](100) # option 1 : afficher directement le résultat
[Link](90) print(addition(3,4))
i=i+1 7

27 28
1.8. Les fonctions 1.8. Les fonctions

while i<nb_carres:
# option 2 : enregistrer le résultat carre(cote) # appel a la fonction carre
a = addition(3,4) deplace(cote+10) # appel a la fonction deplace
print(a) i=i+1 # au suivant !
7
# on peut alors le réutiliser Remarque : on peut même appeler une fonction depuis elle-même, c’est alors une fonction récursive (hors programme
b = addition(a,6) de cette UE).
print(b)
13 1.7.4 Différence entre valeur de retour et effets de bord
Valeur None Certaines fonctions n’ont aucune valeur de retour, mais uniquement des effets de bord : elles On a vu qu’une fonction peut renvoyer une ou plusieurs valeurs de retour, ou aucune ; et qu’elle peut avoir des
modifient leur environnement (affichage de valeurs, tracé turtle, etc) mais ne renvoient aucune valeur. On appelle effets de bord, ou pas. Il faut bien distinguer ces deux concepts.
parfois de telles fonctions des procédures. Dans ce cas il est inutile d’affecter leur résultat dans une variable (puisqu’il • Les valeurs de retour sont des valeurs renvoyées par la fonction, avec le mot-clé return. Ces valeurs peuvent
n’y a pas de résultat). Si on le fait quand même, la variable recevra la valeur spéciale None, qui signifie “aucune valeur” (doivent) être utilisées dans la fonction ou le programme qui appelle cette fonction : on peut les afficher, les
: la variable n’a pas de valeur, mais s’affiche comme ”None”. affecter dans des variables, etc.

>>> z=distance(2, 3, 4, 5) # affectation de la valeur dans une variable • Les effets de bord sont des actions réalisées par la fonction qui modifient son environnement, comme d’afficher
>>> print(z) # affichage de la variable contenant la valeur de retour des éléments à l’écran (avec des instructions comme print ou avec les fonctions du module turtle par
2.8284271247461903 exemple). Les éléments affichés à l’écran ne sont pas utilisables dans la fonction ou le programme appelant !
Seul l’utilisateur peut les visualiser à l’écran quand il exécute le programme.
>>> demander_nom() # effets de bord et valeur de retour Regardons la différence sur un exemple. On peut écrire plusieurs fonctions d’addition, qui reçoivent les entiers à
Quel est ton nom? Carole additionner en paramètre ou via une interaction avec l’utilisateur (effet de bord), et qui affichent le résultat (effet de
’Carole’ bord) ou le renvoient (valeur de retour).
>>> name # on n’a pas sauvé le nom, impossible de l’utiliser
Traceback (most recent call last): # Addition de 2 nombres, RENVOIE la somme

File "<stdin>", line 1, in <module> def addition(x,y): # Addition, demande 2 réels, affiche leur somme
NameError: name ’name’ is not defined return x+y def addition_IO():
>>> name = demander_nom() # version correcte x = float(input("x ?"))
Quel est ton nom? Carole # Addition de 2 nombres, AFFICHE la somme y = float(input("y ?"))
’Carole’ def addition_aff(x,y): print(x+y)
>>> print("Bonjour",name) # on peut utiliser le nom print(x+y)
Bonjour Carole

# fonction qui trace une ligne de carres


# fait appel aux fonctions definies plus haut: carre et deplace
# procédure: pas de valeur de retour, pas d’affectation
def ligne_carres(nb_carres, cote):
>>> carre_standard() # pas d’argument ni valeur de retour
>>> carre(50) # pas de valeur de retour mais des effets de bord (turtle)
>>> x = carre(50) # si on affecte quand meme
>>> x # x n’a pas de valeur
>>> print(x) # il s’affiche comme la valeur spéciale ’None’
None
>>> x+2 # on ne peut rien en faire
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: ’NoneType’ and ’int’

Appel d’une fonction depuis une autre On peut appeler une fonction dans le programme principal, mais
aussi dans le corps d’une autre fonction. Par exemple, en supposant que la fonction carre a été définie précédemment :

# fonction qui deplace le curseur sans tracer


# fait appel aux fonctions turtle: up, forward, down
def deplace(distance):
up()
forward(distance)
down()

29 30
1.8. Les fonctions 1.8. Les fonctions
i=0 # compte les carres déjà tracés

29 30
1.8. Les fonctions 1.8. Les fonctions

Les schémas ci-dessous illustrent les entrées, sorties, et effets de bord de ces fonctions d’addition.

L’appel de ces fonctions depuis un programme principal est donc très différent.

# programme principal

# appel de la fonction d’addition qui renvoie la valeur


somme = addition(3,7) # il faut affecter la valeur dans une
[Link]("la somme vaut",somme) # on peut alors afficher cette var.
# on peut aussi afficher directement la valeur de retour sans
l’affecter# mais alors on ne pourra pas la réutiliser (non stockée)
print("la somme de",5,"et",10,"vaut",somme(5,10))

# appel de la fonction qui affiche


# avec cette fonction on ne peut pas stocker la valeur pour la réutiliser

29 30
1.8. Les fonctions 1.8. Les fonctions

addition_aff(13,25) # pas d’affectation ! la fonction affichera 38 L’exécution de ce programme provoque une erreur : NameError : name ’resultat’ is not defined, ce
a = 12 qui signifie que la variable resultat n’est pas définie dans le programme principal, et donc
b = 25 l’instruction qui essaye d’afficher sa valeur échoue. En effet il s’agit d’une variable locale à la
addition_aff(a,b) # la fonction affichera 37 fonction moyenne, qui n’existe pas dans le programme principal. Par contre sa valeur (renvoyée
addition_aff(10,a) # la fonction affichera 22 par la fonction moyenne) a bien été sauvée dans la variable m lors de l’appel de la fonction.

# appel de la fonction qui demande et affiche Variables du programme principal Une variable (de type int, float, bool ou str) définie
addition_IO() # pas d’affectation, pas de paramètres dans le programme principal ne peut pas être modifiée par une instruction qui se trouve à l’intérieur
# la fonction interagira avec l’utilisateur d’une fonction. Cela ne provoque pas d’erreur mais cela crée une nouvelle variable locale portant le
même identificateur (nom) que l’autre variable. Par exemple :
1.7.5 Portée des variables # fonction qui affiche sa variable locale a
Chaque fonction a son propre "lot" de variables auquel elle a le droit d’accéder. Une variable def affiche_a():
créée ou modifiée dans le corps d’une fonction, ou qui contient un argument de la fonction, est a = 1
dite locale, et ne sera pas accessible depuis le programme principal, ni depuis une autre fonction. print(a)
L’utilisation de Python Tutor permet de visualiser les variables définies dans les différents
environnements (frames) : l’environnement global (global frame) correspond au programme # programme principal qui définit une variable a
principal, et chaque fonction a son propre environnement. Ainsi sur la figure ci-dessous on voit a = 2
l’environnement distance frame contenant les variables locales à la fonction distance. # et appelle la fonction ci-dessus
affiche_a() # la fonction affiche la valeur de son a local, soit 1
# affichage de la variable a du programme principal
print(a) # le prog. principal affiche la valeur de son a local, soit 2
Un autre exemple :
def moyenne(x,y):
# calcule la moyenne de x et y
resultat=(x+y)/2
# crée une nouvelle variable test, locale a la fonction
test=resultat
# renvoie la valeur de la variable resultat
return resultat

# programme principal
a=5
b=6
Exemple de variable locale # variable test, locale au programme principal
test=0
def moyenne(x,y):
m=moyenne(a,b)
# calcule la moyenne de x et y, et l’affecte dans une variable locale
print("m =", m) # affiche "m=5.5"
resultat=(x+y)/2
print("test =",test) # affiche "test=0"
# renvoie la VALEUR de cette variable locale
return resultat Ce programme principal initialise à 0 une variable locale test. Ensuite, l’appel à la fonction
moyenne crée une nouvelle variable, aussi nommée test, mais locale à cette fonction. Cet appel
# programme principal ne modifie donc pas la valeur de la variable test du programme principal. L’instruction print
a=5 affiche donc cette valeur non modifiée, c-à-d 0.
b=6
m=moyenne(a,b) # affectation de la valeur de retour dans une variable Variables globales Une variable peut être définie comme globale (mot-clé global) pour pouvoir être
print(m) # affiche 5.5 modifiée partout. Cependant, il faut éviter cette pratique. Cela complique le code inutilement et
print(resultat) # provoque une erreur risque d’entraîner des modifications indésirables ailleurs dans le programme.

31 32
1.8. Les fonctions 1.9. Importation de modules

Attention ! Les variables définies dans le programme principal sont en fait accessibles en • On évitera les variables globales.
lecture seule (on peut les lire mais pas les modifier) depuis l’intérieur d’une fonction, mais ce
comportement est dangereux car très subtil. On ne l’utilisera donc pas (sauf éventuellement pour • On affectera la valeur de retour d’une fonction dans une variable pour pouvoir la réutiliser ; les
des variables "constantes", initialisées une fois au début du programme et jamais modifiées ensuite). On procédures ne renvoient rien et on les appelle donc sans affecter le résultat dans une variable
préférera passer en arguments toutes les valeurs nécessaires. (valeur None).
Par exemple, voici 2 manières de définir une fonction qui décale une chaîne de n tirets. Dans la
première version (incorrecte) on utilise la variable n définie dans le programme principal, que la
fonction peut lire. Cela fonctionne, mais la fonction est mal définie, si elle a besoin de l’information 1.8 Importation de modules
n alors cela devrait être un argument. Dans la deuxième version (correcte), la valeur de n est reçue
en paramètre, et affectée dans la variable n locale à la fonction. C’est la bonne façon de définir cette Un grand nombre de fonctions sont déjà définies en Python, et sont rangées dans des modules sur
fonction. un thème spécifique. Pour utiliser ces fonctions, il faut d’abord importer le module correspondant.
Les syntaxes possibles pour importer un module sont les suivantes :
# version incorrecte, utilise le n du prog. principal en lecture seule
def decalage(s): import nom_module # préfixer ensuite les fonctions par le nom du module
return ("-" * n) + s from nom_module import nom_fonction # importer une fonction specifique,
# pas besoin de préfixer son nom
# depuis l’interpréteur from nom_module import * # importer toutes les fonctions du module,
>>> n=5 # pas besoin de prefixer leurs noms
>>> print(decalage("toto"))
- --- toto import [Link] as plt # renommage module pour simplifier appel

# version correcte, reçoit valeur en param. et l’affecte dans le n local Le mot clé as permet de créer un ’raccourci’ pour appeler les fonctions d’un module. C’est
def decalage(s, n): pratique quand le nom du module est assez long, puisqu’il faut préfixer l’appel de chaque fonction
return ("-" * n) + s par le nom du module. Par exemple pour [Link] ci-dessus, on pourra maintenant
appeler les fonctions en les préfixant uniquement par plt au lieu du nom complet du module.
# depuis l’interpréteur
>>> print(decalage("toto", 5))
Modules utiles Quelques modules intéressants :
- --- toto
>>> print(decalage("maison",10))
• math : regroupe les fonctions mathématiques les plus courantes
maison
• random : génération de nombres pseudo-aléatoires
Variables modifiables Nous avons vu que les variables de types simples définies dans le
programme principal ne sont pas modifiables dans les fonctions appelées. Il y a une exception • turtle : librairie graphique pour l’apprentissage de la programmation
avec les types complexes que nous verrons plus tard. Par exemple le type liste (Chapitre 1.11) [Link]
permet de stocker une liste de plusieurs valeurs. Ces types complexes fonctionnent un peu
différemment des types simples, et en particulier ils peuvent être modifiés par une fonction (ce • os : manipulation de fichiers, dossiers, chemins d’accès, permissions...
sera un nouveau type d’effet de bord).
• Tkinter : interface graphique par défaut
Résumé

• Une variable créée ou modifiée dans une fonction est locale, elle n’existe que dans la 1.9 Chaînes de caractères
fonction.
1.9.1 Type string
• Une variable simple (de type int, float, str ou bool) du programme principal peut être lue
mais ne peut pas être modifiée à l’intérieur d’une fonction. On verra plus tard que c’est Les chaînes de caractères (string en Python) sont un type de données, plus complexe que
différent pour les types complexes (listes ). ceux vus jusqu’à présent. Il s’agit d’un type itérable, c’est-à-dire dont on peut parcourir les valeurs
(ici les différents caractères qui composent la chaîne). On verra d’autres types itérables plus tard
• On passera en argument des fonctions toutes les valeurs nécessaires à leur fonctionnement. (listes, dictionnaires).

33 34
1.10. Chaînes de caractères 1.10. Chaînes de caractères

Syntaxe On a déjà utilisé les chaînes de caractères, notamment dans les fonctions print() et Caractères d’échappement Le caractère pe\rmet d’utiliser des caractères spéciaux dans une chaîne
input(). En Python, il existe 3 syntaxes pour les chaînes de caractères : de caractères :

• Avec des guillemets doubles, ce qui permet d’utiliser des guillemets simples (apostrophes) • \′ est une apostrophe mais ne ferme pas la chaîne de caractères (même si entre apostrophes)
dans le texte :
• \” est une guillemet double, mais il ne ferme pas la chaîne de caractères
print("je m’appelle toto")
• \n : retour à la ligne
• Avec des apostrophes, ce qui permet d’utiliser des guillemets doubles dans le texte :
• \t : tabulation
print(’il a dit "bonjour" en arrivant’)
• \\ : si on veut insérer un caractère \ (’backslash’)
• Avec des guillemets triples, ce qui permet de créer de longues chaînes contenant des
guillemets, des apostrophes, des sauts de ligne... :
Exemples
print("""il m’a dit "je m’appelle toto" puis est parti""")
>>> print("il a dit \"bonjour\" en arrivant")
Exemples il a dit "bonjour" en arrivant

>>> print("C’est toto")


1.9.3 Opérateurs sur les chaînes
C’est toto
>>> print(’C’est toto’) Concaténation L’opérateur + permet de concaténer plusieurs chaînes de caractères, c’est-à-dire de
SyntaxError : invalid syntax les coller l’une après l’autre pour former une seule chaîne.
>>> print("Il a dit "hello" !")
SyntaxError : invalid syntax >>> nom = input("Ton nom ? ")
>>> print(’Il a dit "hello" !’) Ton nom ? toto
Il a dit "hello" ! >>> salutation = "bonjour "+nom
>>> print("""C’est toto qui a dit "hello" !""") >>> print(salutation)
C’est toto qui a dit "hello" ! bonjour toto
>>> print("""C’est toto qui a dit "hello"""")
SyntaxError : ... >>> "abc" + "def"
’abcdef’
1.9.2 Caractères
Répétition L’opérateur * permet de concaténer plusieurs fois la même chaîne.
Table ASCII Une chaîne est formée de caractères, qui sont représentés chacun par un code ASCII
unique (cf tableau ci-dessous). Ainsi les lettres minuscules ont des codes ASCII entre 97(’a’) et
>>> x = int(input("Combien ? "))
122 (’z’), les lettres majuscules ont des codes ASCII entre 65 (’A’) et 90 (’Z’). Le tableau contient
Combien ? 7
aussi des caractères numériques (’0’, ’1’, etc) et divers caractères spéciaux.
>>> print(x*’*’) # affiche x symboles etoile
*******
Fonctions ord() et chr() Ce tableau est à la fin du chapitre, mais il n’est pas nécessaire de connaître >>> print(’+’*x) # affiche x symboles +
ces codes ASCII ! Les opérateurs ord() et chr() permettent de les retrouver : +++++++
>>> ord(’a’) # trouver le code ASCII d’un caractere
97 >>> "ta " * 4
>>> ord(’@’) ’ta ta ta ta’
64
>>> chr(99) # trouver le caractere correspondant a un code ASCII Comparaison Les opérateurs de comparaison <,>,<=,>=,==, != peuvent s’utiliser entre des chaînes
’c’ de caractères. Il s’agit alors d’une comparaison dans l’ordre de la table ASCII (voir le tableau
>>> chr(123) plus loin) : la comparaison respecte l’ordre alphabétique, les majuscules sont avant les minuscules,
’{’ les chaînes plus courtes sont avant les chaînes plus longues qui ont le même début.

35 36
1.10. Chaînes de caractères 1.10. Chaînes de caractères

>>> ’abc’ < ’a’ Compter On peut aussi vouloir compter le nombre d’occurrences (d’apparitions) d’une chaîne dans
False une autre, avec la fonction count(). Par exemple :
>>> ’abc’ < ’abca’
True >>> "toto".count("o")
>>> ’abc’ < ’z’ 2
True >>> "toto".count("to")
2
>>> ’a’ < ’A’ # les majuscules sont avant dans la table ASCII >>> "toto".count("ot")
False 1
>>> ’A’ == ’a’ # respect de la casse >>> "toto".count("a")
False 0
>>> ’A’ < ’a’
True Test de casse On appelle casse d’une chaîne de caractère le fait de savoir si elle est en majuscules
>>> ’toto’ < ’toto aaa’ (haut de casse) ou en minuscules (bas de casse). Python fournit plusieurs fonctions pour tester ou
True modifier la casse d’une chaîne.

>>> x = ’R’ # affectation >>> ’toto’.isupper() # est en majuscules ?


>>> ’a’ <= x <= ’z’ # x est-elle une lettre minuscule de l’alphabet? False
False >>> ’Toto’.isupper()
>>> ’A’ <= x <= ’Z’ # x est-elle une lettre majuscule? False
True >>> ’TOTO’.isupper()
True
>>> ’toto’.islower() # est en minuscules ?
1.9.4 Fonctions de manipulation de chaînes
True
On retrouvera ces mêmes fonctions sur les listes. >>> ’toTo’.islower()
False
Longueur La fonction len() renvoie la longueur d’une chaîne de caractères. >>> ’ToTo azerty’.lower() # passer en minuscules
’toto azerty’
>>> s = "abcde"
>>> ’ToTo azerty’.upper() # passer en majuscules
>>> len(s)
’TOTO AZERTY’
5
>>> ’bonjour a tous’.capitalize() # une majuscule au début
>>> len(’toto’)
’Bonjour a tous’
4

Test d’appartenance Le mot-clé in permet de vérifier si une chaîne (ou un caractère) est inclue Découpage et recollage Il existe différentes fonctions pour découper des chaînes de caractères.
dans une autre. Par exemple : La fonctionlist() fournit la liste de tous ses caractères (espaces compris). La fonction split()
renvoie une liste de chaînes résultant du découpage autour d’un séparateur optionnel fourni en
>>> "a" in "toto" paramètre (ou espace par défaut) ; le séparateur n’apparaît plus dans les éléments. A partir d’une
False liste de chaînes, join() fait l’opération inverse et les recolle ensemble, séparées par une chaîne.
>>> "o" in "toto" Les exemples ci-dessous illustrent la syntaxe de ces fonctions.
True
>>> "to" in "toto" >>> s = "bonjour a tous"
True >>> list(s) # liste des caractères de s
>>> "abc" in "toto" [’b’, ’o’, ’n’, ’j’, ’o’, ’u’, ’r’, ’ ’, ’a’, ’ ’, ’t’, ’o’, ’u’, ’s’]
False >>> [Link]() # découpage de s autour du car. espace (par défaut)
>>> "abc" in "abcd" [’bonjour’,’a’,’tous’]
True >>> [Link](’o’) # découpage autour de la lettre ’o’
>>> "acb" in "abcd" [’b’, ’nj’, ’ur a t’, ’us’]
False >>> ls=[’toto’,’titi’,’abc’,’azerty’] # liste de chaînes de caractères

37 38
1.10. Chaînes de caractères

>>> ’-’.join(ls)
’toto-titi-abc-azerty’
table ASCII
>>> ’’.join(ls) # recollage autour d’une chaîne vide = concaténation
’tototitiabcazerty’

1.9.5 Parcours de chaînes (nécessite le cours sur les boucles)


Les chaînes de caractères sont des structures itérables (comme les listes ou les dictionnaires 000 NUL (Null Character) 033 ! 065 A 097 a
que nous verrons plus tard). Avec une chaîne s, on peut accéder à l’élément à une position i donnée
001 SOH (Start of Header) 034 “ 066 B 098 b
(i est appelé l’indice) avec la notation s[i]
002 STX (Start of Text) 035 # 067 C 099 c
On peut aussi parcourir tous les éléments d’une chaîne, par itération sur les indices avec une boucle
while (cf chapitre 1.7), ou par itération directement sur les éléments avec une boucle for (cf 003 ETX (End of Text) 036 $ 068 D 100 d
chapitre 1.12). 004 EOT (End of Transmission) 037 % 069 E 101 e
005 ENQ (Enquiry) 038 & 070 F 102 f
>>> s = "bonjour a tous"
>>> s[0] # le premier caractère de la chaîne 006 ACK (Acknowledgement) 039 ' 071 G 103 g
’b’ 007 BEL (Bell) 040 ( 072 H 104 h
>>> s[-1] # le dernier caractère de la chaîne 008 BS (Backspace) 041 ) 073 I 105 i
’s’ 009 HT (Horizontal Tab) 042 * 074 J 106 j
>>> s[3] # le caractère à l’indice 3 (le 4e de la chaîne)
010 LF (Line Feed) 043 + 075 K 107 k
’j’
011 VT (Vertical Tab) 044 , 076 L 108 l
>>> s = ’hello’ 012 FF (Form Feed) 045 - 077 M 109 m
>>> i=0 # initialisation du compteur de boucle 013 CR (Carriage Return) 046 . 078 N 110 n
>>> while i<len(s): # répétition jusqu’à la longueur de la chaîne 014 SO (Shift Out) 047 / 079 O 111 o
>>> print(s[i]) # afficher le i-ième caractère de s 015 SI (Shift In) 048 0 080 P 112 p
>>> i+=1 # penser à incrémenter le compteur
016 DLE (Data Link Escape) 049 1 081 Q 113 q
h
e 017 DC1 (XON) (Device Control 1) 050 2 082 R 114 r
l 018 DC2 (Device Control 2) 051 3 083 S 115 s
l 019 DC3 (XOFF) (Device Control 3) 052 4 084 T 116 t
o 020 DC4 (device control 4) 053 5 085 U 117 u
021 NAK (Negative Acknowledgement) 054 6 086 V 118 v
>>> for e in s: # itération directement sur les caractères
>>> print(e) 022 SYN (Synchronous Idle) 055 7 087 W 119 w
h 023 ETB (End of Transmission Block) 056 8 088 X 120 x
e 024 CAN (Cancel) 057 9 089 Y 121 y
l 025 EM (End of Medium) 058 : 090 Z 122 z
l
026 SUB (Substitute) 059 ; 091 [ 123 {
o
027 ESC (Escape) 060 < 092 \ 124 |
028 FS (File Separator) 061 = 093 ] 125 }
029 GS (Group Separator) 062 > 094 ^ 126 ~
030 RS (Request to Send) 063 ? 095 _ 127 DEL
031 US (Unit Separator) 064 @ 096 `
032 SP (Space)

39
1.11. Listes 1.11. Listes

1.10 Listes 1.10.2 Numérotation des éléments et accès

1.10.1 Type liste en Python Une liste est un ensemble ordonné. Cela signifie que les éléments sont dans un ordre donné, et qu’on
peut accéder à un élément à partir de son numéro, qu’on appelle son indice. Les éléments sont
Types simples vs types complexes. On a manipulé jusqu’à maintenant plusieurs types de données indexés (numérotés) à partir de 0, c-à-d que le premier élément a pour indice (position, numéro) 0.
: les entiers (int), les réels (float), les booléens (bool), les chaînes de caractères (str). Il s’agit de En conséquence, pour une liste de n éléments, le dernier élément est à l’indice n-1. Il n’y a pas
types simples, c’est-à-dire ne contenant qu’une seule valeur. Mais on a parfois besoinde d’élément à l’indice n.
manipuler des structures de données plus complexes, comme des listes, des ensembles, des
tableaux à plusieurs dimensions (matrices), etc.
Accès à un élément Pour accéder à l’élément d’indice i d’une liste maliste, on écrit maliste[i].
>>> a = 6 Attention, i doit être strictement inférieur à la taille de la liste, sinon on obtient une erreur. Chaque
>>> type(a) élément est une variable qui peut donc être lue et modifiée.
<class ’int’>
>>> weekend=["samedi","dimanche"]
>>> type(3.5)
>>> weekend[0]
<class ’float’>
’samedi’
>>> type(True)
>>> weekend[1]
<class ’bool‘>
’dimanche’
>>> type(’bonjour’)
>>> weekend[2]
<class ’str’>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Listes. En Python, une liste est un ensemble ordonné d’éléments. Elle est nommée par un identi- IndexError: list index out of range
ficateur (comme n’importe quelle variable). Une liste peut grandir (ou se réduire) dynamiquement,
c’est-à-dire qu’on peut y ajouter ou en enlever des éléments : sa taille n’est pas fixe. Une liste peut On peut aussi accéder aux éléments en comptant à partir de la fin de la liste, avec un indice
contenir des éléments de types différents, y compris d’autres listes. Les éléments sont notés entre négatif. L’indice -1 correspond au dernier élément, l’indice -2 à l’avant-dernier, etc. Là aussi, si
crochets, séparés par des virgules. l’indice va trop loin, on déclenche une erreur.

# initialisation de diverses listes >>> weekend[-1]


weekend=["Samedi","Dimanche"] # liste de chaînes de car. ’dimanche’
multiple3 = [3, 6, 9, 12] # liste d’entiers >>> weekend[-2]
romain = [[1,’I’],[2,’II’], [3,’III’],[4,’IV’]] # liste de listes ’samedi’
iv = 4 >>> weekend[-3]
fourreTout = ["Un", 2, 3.0, iv] # liste contenant plusieurs types d’éléments Traceback (most recent call last):
vide = [] # liste vide File "<stdin>", line 1, in <module>
IndexError: list index out of range
Opérateurs utiles Certains opérateurs arithmétiques fonctionnent sur les listes : + correspond à
une concaténation, * à une répétition. Cela permet d’initialiser rapidement des listes répétitives. Longueur d’une liste Pour connaître la longueur d’une liste, on utilise la fonction len(). Par
exemple avec les listes précédentes :
>>> l1 = [1,2,3]
>>> l2 = [4,5,6] >>> len(weekend)
>>> l1+l2 2
[1,2,3,4,5,6] >>> len(romain)
>>> l = [’C’] + 10*[’I’] # utile pour le TP « propagation nouvelle » 4
>>> l
[’C’, ’I’, ’I’, ’I’, ’I’, ’I’, ’I’, ’I’, ’I’, ’I’, ’I’] 1.10.3 Recherche dans une liste
>>> len(l)
11 Test d’appartenance d’un élément : in Le mot-clé in permet de tester si un élément donné est dans
>>> 3 * [2] une liste donnée. L’expression elem in l est évaluée à True si la liste l contient l’élément elem, et
[2,2,2] à False si elle ne le contient pas.

41 42
1.11. Listes 1.11. Listes

>>> ma_liste=[2,5,8,12,17,25,2,7,2,1] >>> l1=[1,2,3] # crée une liste


>>> 2 in ma_liste >>> print(l1) # l’affiche sous forme standard
True [1,2,3]
>>> 3 in ma_liste >>> print(l1,sep=’-’) # le séparateur ne sert à rien, 1 seul argument
False [1, 2, 3]
>>> print(l1,"toto",sep=’-’) # séparateur entre la liste et la chaîne
Compter un élément : count Par contre in ne nous dit pas combien de fois l’élément apparaît,s’il [1, 2, 3]-toto
est contenu plusieurs fois dans la liste. Pour cela on dispose de la fonction count.
>>> ma_liste.count(2) Affichage avec boucle while Si on veut personnaliser l’affichage, il faut parcourir les éléments un
3 par un avec une boucle.
>>> ma_liste.count(31)
0 # procédure d’affichage d’une liste reçue en paramètre
def afficheET(liste):
Position d’un élément : index Si on veut savoir non seulement si un élément est dans une liste, i = 0
while i<len(liste):
mais où il se situe dans cette liste (son indice) alors on utiliser la fonction index. Les indices
print(liste[i],"et",end=" ")
commencent à 0, le premier élément est en position 0, le 2e en position 1, etc. Si un élément n’est
# affichage personnalisé sans retour ligne
pas dans la liste, la fonction déclenche une erreur. Si un élément est plusieurs fois dans la liste, la
i += 1 # élément suivant
fonction renvoie l’indice de sa première occurrence (première apparition).
print() # retour à la ligne final
>>> ma_liste.index(5) # appel dans l’interpréteur
1 >>> prenoms = [’toto’,’titi’,’yoyo’,’mumu’]
>>> ma_liste.index(2) >>> afficheET(prenoms)
0 # pour éviter le et final il faudrait traiter le dernier élément à part
>>> ma_liste.index(9) toto et titi et yoyo et mumu et
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 9 is not in list Affichage avec boucle for Les boucles for (chapitre 1.12) permettent d’itérer directement sur les
éléments d’une liste plutôt que sur leur indice, et donc de simplifier l’écriture. Par exemplepour
On peut définir une fonction indice qui vérifie qu’un élément est dans la liste avant de chercher afficher un élément par ligne plutôt que l’affichage standard entre crochets.
sa position. Par convention, cette fonction renvoie la position -1 pour signifier que l’élément n’est
pas trouvé dans la liste. def afficheFOR(liste):
for elem in liste:
def indice(liste,i):
if i in liste: print(elem) # retour ligne auto à chaque élément
return [Link](i)
else: # appel depuis l’interpréteur
return -1 >>> l = [’a’,’b’,’c’]
>>> afficheFOR(l)
# dans l’interpréteur a
b
>>> indice(ma_liste,2)
c
0
>>> indice(ma_liste,9)
-1 1.10.5 Modifier et ajouter des éléments
Modification d’une valeur Pour modifier la valeur d’un élément, il suffit de lui affecter une
1.10.4 Affichage
nouvelle valeur. Attention encore à utiliser un indice existant. On ne peut pas affecter de valeur à un
Affichage standard avec print La fonction print déjà utilisée pour afficher des variables de types élément qui n’est pas encore dans la liste, là aussi on déclenche une erreur (index out of range
simples est aussi capable d’afficher des listes. Par contre le paramètre optionnel sep ne sertà rien = dépassement des limites de la liste). (Ce n’est donc pas comme cela qu’il faut procéder pour ajouter
: il s’agit d’un séparateur entre les paramètres de print, or ici il n’y en a qu’un, la liste. un nouvel élément dans la liste ; on dispose pour cela d’opérateurs dédiés.)

43 44
1.11. Listes 1.11. Listes

>>> weekend[0] = ’saturday’ >> multiple3[3] # on vérifie


>>> weekend 15
[’saturday’, ’dimanche’] >>> multiple3
>>> weekend[1] = ’sunday’ [3, 6, 9, 15, 21]
>>> weekend >>> [Link](7,24) # 7 est trop grand: insertion à la fin
[’saturday’, ’sunday’] >>> multiple3
>>> weekend[2] = ’lundi’ [3, 6, 9, 15, 21, 24]
Traceback (most recent call last): >>> [Link](-7,12) # -7 est trop petit: insertion au début
File "<stdin>", line 1, in <module> >>> multiple3
IndexError: list assignment index out of range [12, 3, 6, 9, 15, 21, 24]

Ajout d’un seul élément en fin de liste : append Pour ajouter un seul élément e à la fin d’une liste Ajout de plusieurs éléments : extend Pour ajouter plusieurs éléments d’un seul coup à la fin d’une
l, on utilise la fonction [Link](e). Cette fonction modifie directement la liste (effet de bord), liste, on peut utiliser [Link](liste2) qui reçoit une deuxième liste en paramètre,et ajoute
elle ne renvoie rien. Attention donc à ne surtout pas affecter son résultat dans la liste elle-même, tous ses éléments à la fin de la liste. Attention, ce n’est pas l’élément liste2 (un élément de type
sinon on l’écrase ! liste) qu’on ajoute comme un élément de liste, mais bien les éléments qu’elle contient (plusieurs
éléments de type entier). Attention, extend reçoit un seul paramètre, qui doit être une liste (même
>>> Multiple3 = [3, 6, 9]
si elle contient un seul élément).
>>> [Link](12)
>>> Multiple3 # avec extend, les éléments de la 2e liste sont ajoutés dans la 1e
[3, 6, 9, 12] >>> multiple3 = [3,6,9,15,21]
>>> [Link](21) >>> [Link]([24,27])
>>> Multiple3 >>> multiple3
[3, 6, 9, 12, 21] [3, 6, 9, 15, 21, 24, 27]
>>> x = [Link](7) # avec append, c’est la liste qui est ajoutée en fin de liste
>>> Multiple3 # 7 a bien été ajouté en fin de liste >>> multiple3 = [3,6,9,15,21]
[3,6,9,12,7] >>> [Link]([24,27])
>>> x # mais x n’a reçu aucune valeur >>> multiple3
>>> print(x) [3, 6, 9, 15, 21, [24,27]]
None # extend reçoit un seul paramètre de type liste
>>> Multiple3 = [Link](18) # à ne SURTOUT PAS faire >>> [Link](24,27) # erreur, 2 entiers au lieu d’une liste
>>> Multiple3 # on a perdu notre liste Traceback (most recent call last):
>>> print(Multiple3) File "<stdin>", line 1, in <module>
None TypeError: extend() takes exactly one argument (2 given)
>>> [Link](24) # erreur, 24 est un entier et pas une liste
Insertion d’un élément à une position voulue : insert Pour insérer un seul élément, non pas en Traceback (most recent call last):
fin de liste mais à une position donnée, on utilise [Link](index,element). Si l’indice File "<stdin>", line 1, in <module>
donné est trop grand (dépasse la taille de la liste), alors l’élément est inséré en fin de liste (pas TypeError: ’int’ object is not iterable
d’erreur). On peut aussi donner une position négative, qui est alors comptée à partir de la fin de # il faut passer une liste, même si c’est un singleton
la liste. De même, si cet indice négatif est trop petit (avant le début de la liste), l’élément est inséré >>> [Link]([30])
en tout début de liste. Cette fonction modifie directement la liste (effet de bord) mais ne renvoie >>> multiple3
rien. [3, 6, 9, 15, 21, 24, 27, 30]
Remarque : l’insertion d’un élément est plus coûteuse en calcul que append car elle implique de
décaler les autres éléments en mémoire. 1.10.6 Supprimer des éléments
>> multiple3 = [3, 6, 9, 21] Supprimer un élément à une position donnée : pop La fonction [Link](index) retire
>> [Link](3,15) # insérer en position 3 l’élément 15 l’élément présent à la position index et le renvoie. La fonction pop modifie directement la liste (effet
>> multiple3 de bord), et renvoie l’élément supprimé (valeur de retour) ; on peut donc l’affecter dans une variable
[3, 6, 9, 15, 21] pour le récupérer. Si l’indice donné est hors des limites possibles, l’appel déclenche une

45 46
1.11. Listes 1.11. Listes

erreur. Si on ne fournit pas d’indice (paramètre optionnel), la fonction retire et renvoie le dernier Copie/clonage de surface : list() La fonction list() opère une copie de surface : elle crée une
élément de la liste. nouvelle liste contenant les mêmes éléments que la liste initiale. Il s’agira bien de 2 listes distinctes.
Les modifications apportées à une des listes après la copie n’affecteront pas l’autre liste.
>>> multiple3 = [3, 6, 9, 15, 21, 24, 27, 24, 24]
>>> a = [Link](0) liste1=[1,2,3] # création de liste1
>>> a liste3=list(liste1) # copie de liste1 dans liste3
3 [Link]("bip") # modification de liste3
>>> multiple3 >>> liste3
[6, 9, 15, 21, 24, 27, 24, 24] [1, 2, 3, ’bip’]
>>> b = [Link](27) # erreur, indice 27 trop grand >>> liste1 # liste1 n’a pas été modifiée
Traceback (most recent call last): [1, 2, 3]
File "<stdin>", line 1, in <module>
IndexError: pop index out of range
Visualisation On peut utiliser Python Tutor pour bien visualiser ce qui se passe. Sur la première capture
>>> b = [Link]()
d’écran ci-dessous, on a utilisé une simple affectation liste2=liste1, les 2 variables pointent donc
>>> b
vers la même liste : on lui a donné 2 noms. Sur la deuxième capture d’écran on a utilisé list pour faire
24
une copie (de surface) de liste1 dans liste3. Les 2 variables correspondentbien à 2 listes différentes.
>>> multiple3
[6, 9, 15, 21, 24, 27, 24]

Supprimer un élément de valeur donnée : remove. La fonction [Link](element)


retire l’élément de valeur donnée. S’il est présent plusieurs fois dans la liste, uniquement la première
FIGURE 1.1 – Affectation (renommage) : liste2 = liste1
valeur trouvée est supprimée. S’il n’est pas présent, l’appel déclenche une erreur. La fonction
remove modifie directement la liste (effet de bord) et ne renvoie rien.

>>> multiple3
[6, 9, 15, 21, 24, 27, 24, 24]
>>> [Link](24) # retirer le premier 24 trouvé
>>> multiple3
[6, 9, 15, 21, 27, 24, 24]
>>> [Link](47) # erreur, tentative de supprimer un elt absent
Traceback (most recent call last): FIGURE 1.2 – Copie de surface : liste3 = list(liste1)
File "<stdin>", line 1, in <module>
ValueError: [Link](x): x not in list

1.10.7 Copie et clone de listes Le module copy Le module copy contient plusieurs fonctions génériques permettant de copierdes
variables de différents types. Pour les utiliser il faut d’abord importer ce module avec l’instruction
Renommage de liste Attention : l’opérateur = (affectation) permet juste de donner 2 noms à la
import copy. La fonction [Link]() permet de réaliser une copie de surface. La fonction
même liste. Avec une simple affectation, on donne un deuxième identificateur à la même liste, mais
[Link]() permet de réaliser une copie profonde, ou récursive.
on n’en crée pas de nouvelle. Les deux identificateurs réfèrent toujours à la même liste, et donc les
modifications apportées à une des variables après l’affectation s’appliquent également à l’autre >>> import copy
variable. >>> liste = [1,2,3]
liste1=[1,2,3] # création de liste1 >>> copie = [Link](liste)
liste2=liste1 # liste2 est un autre nom pour liste1 >>> [Link](4)
[Link]("bip") # si on modifie liste2 >>> copie
>>> liste2 [1, 2, 3, 4]
[1, 2, 3, ’bip’] >>> liste
>>> liste1 # on modifie aussi liste1 [1, 2, 3]
[1, 2, 3, ’bip’]

47 48
1.11. Listes 1.12. Boucle inconditionnelle : for

Copie de surface vs copie profonde Si une liste contient d’autres listes, pour la copier correc- Exemple avec oubli de la copie
tement il faut utiliser la fonction deepcopy du module copy, qui va faire une copie profonde,
récursive, c’est-à-dire qu’elle va aussi faire des copies des listes contenues dans la liste copiée. Pour import random
une liste simple, une copie de surface suffit.
def ajoute_random(l):
>>> liste1 """Liste obtenue à partir de l en ajoutant un entier aléatoire entre
[1, 2, 3, [’a’, ’b’, ’c’], 4] 5 et 10"""
>>> surface = [Link](liste1) x=[Link](5,10)
>>> profonde = [Link](liste1) [Link](x)
>>> surface # copie de surface, liste d’indice 3 non clonée return l
[1, 2, 3, [’a’, ’b’, ’c’], 4]
>>> profonde Cette fonction modifie la liste reçue en paramètre (effet de bord) et renvoie la liste modifiée (valeur
[1, 2, 3, [’a’, ’b’, ’c’], 4] de retour). En fait il est inutile de renvoyer la liste, puisqu’on l’a modifiée directement. Ainsi
>>> surface[3].append(’d’) # si on modifie la liste surface[3]
>>> l = [1,2,3]
>>> surface
>>> l2 = ajoute_random(l)
[1, 2, 3, [’a’, ’b’, ’c’, ’d’], 4]
>>> l2
>>> liste1 # alors on la modifie aussi ds liste1 (la même)
[1, 2, 3, 8]
[1, 2, 3, [’a’, ’b’, ’c’, ’d’], 4]
>>> l
>>> profonde[3].append(’e’) # copie profonde/récursive: liste clonée
[1, 2, 3, 8]
>>> profonde # si on modifie profonde[3]
>>> [Link](5)
[1, 2, 3, [’a’, ’b’, ’c’, ’e’], 4]
>>> l
>>> liste1 # on ne modifie pas liste[3]
[1, 2, 3, 8, 5]
[1, 2, 3, [’a’, ’b’, ’c’, ’d’], 4]
>>> l2
[1, 2, 3, 8, 5]
1.10.8 Effets de bord avec les listes
On remarque qu’en fait on a ici donné un deuxième identificateur (l2) pour nommer la même
Une fonction peut modifier une liste passée en argument, indépendamment de sa valeur de retour. liste (l). Et surtout, on a modifié notre liste initiale l alors qu’on ne le souhaitait pas. La version
C’est une nouvelle forme d’effet de bord. Les modifications apportées à la liste dans la fonction sont
correcte de cette fonction est donc la suivante :
conservées après la sortie de la fonction, donc dans le programme appelant. Attention aux effets de
bord non désirés ! Il faut donc éviter qu’une fonction modifie une liste si ce n’est pas prévu, ou alors import random
bien penser à copier la liste initiale avant de la passer en argument si on ne souhaite pas qu’elle def ajoute_random(l):
soit modifiée par la fonction. """Liste obtenue a partir de l en ajoutant un entier aléatoire entre
Par exemple imaginons une fonction qui insère un élément en début et fin de liste. 5 et 10"""
x=[Link](5,10)
ma_liste=list(l) # faire une copie de l
ma_liste.append(x) # modifier la copie et pas l’original
return ma_liste # renvoyer la nouvelle, différente de l’original

Cette nouvelle version de la fonction crée et renvoie une nouvelle liste. La liste reçue en argument
n’est pas modifiée. Il n’y a donc pas d’effets de bord. Attention il faut bien utiliser une fonction
de copie et pas une simple affectation (copie = l), qui ne crée pas de copie et donc conduit à
modifier quand même la liste initiale.

1.11 Boucle inconditionnelle : for


1.11.1 Boucles conditionnelles vs inconditionnelles
Dans une boucle while, c’est la condition qui détermine le nombre de fois que la boucle sera
exécutée. Il s’agit d’une boucle conditionnelle. La boucle continue tant que la condition est vraie,

49 50
1.12. Boucle inconditionnelle : for 1.12. Boucle inconditionnelle : for

c-à-d jusqu’à ce que la condition soit fausse. Le plus souvent on ne sait pas combien de fois la Exemples
boucle va se répéter.
Si on connaît à l’avance le nombre de répétition, on peut utiliser le for qui est une boucle # affiche les entiers de 1 à 5 (6 exclus) séparés par une virgule
inconditionnelle. Au lieu de spécifier une condition de répétition, on spécifie directement le for i in range(1,6) :
nombre d’itérations ; la boucle se répète exactement ce nombre de fois. On peut aussi parcourir des print (i,end=",") # affichage de chaque entier suivi d’une virgule
structures itérables (comme les listes) : la boucle se termine alors à la fin du parcours. print() # retour à la ligne à la fin de la sequence

1.11.2 Boucle for pour répéter n fois, fonction range() # affiche les entiers pairs de 0 à 100 (un par ligne)
for i in range(0,101,2) :
Fonction range(). La fonction range(deb, fin, pas) reçoit 3 arguments de type entier, et print(i)
génère une séquence d’entiers compris entre deb inclus et fin exclus, avec le pas choisi. Les
paramètres deb et pas sont optionnels. La borne inférieure deb vaut 0 par défaut, et le pas vaut # affiche les entiers en ordre décroissant de 10 (inclus) à 0 (exclus)
1 par défaut. On peut choisir un pas négatif pour une séquence décroissante d’entiers ; dans ce for i in range(10,0,-1) :
cas fin doit être <= deb, sinon la séquence est vide. print(i)
• range(a) : séquence des entiers dans [0, a[, c’est-à-dire dans [0, a-1] (borne sup exclue)
avec un pas de 1. Boucle while vs for Quand on connaît à l’avance le nombre d’itérations souhaitées, la boucle
• range(b,c) : séquence des valeurs [b, c[, c’est-à-dire dans [b, c-1] (b inclue, c exclue) avec for est beaucoup plus concise. Par exemple, si on veut afficher les entiers de 0 à n.
un pas de 1
# avec un while
• range(e, f, g) : séquence des valeurs [e, f[ avec un pas de g i=0 # initialisation compteur
Remarque : comme les arguments ne sont pas nommés, c’est la position des valeurs qui détermine while i<=n : # condition
à quel argument elles sont affectées (cf chapitre 1.14). On ne peut donc pas omettre la valeur de print(i)
début si on veut préciser le pas. i = i+1 # incrementation compteur
# fin de la boucle quand i depasse n
Utilisation avec for Quand on veut écrire une boucle inconditionnelle avec n répétitions, le plus
simple est donc d’utiliser range(n) pour générer une séquence de n entiers. # avec un for
for i in range(n+1): # range avec n+1 valeurs a partir de 0
for var in range(n) : print(i)
instructions
# fin du for apres exactement n+1 iterations
Plus généralement, si on veut parcourir les entiers entre deb et fin, avec un pas donné, on peut
spécifier les 3 arguments de range.
1.11.3 Parcours de structures itérables
for var in range(deb, fin, pas) :
instructions La boucle for permet aussi de parcourir des structures : listes, chaînes de caractères, etc. Dans
ce cas au lieu d’un compteur de boucle, on utilise une variable qui prend successivement pour
Syntaxe. Comme pour le if et le while, c’est l’indentation des instructions qui détermine si elles sont valeurs tous les éléments contenus dans la structure parcourue (tous les éléments d’une liste, toutes les
dans le bloc for (et donc répétées), ou après la fin du bloc (et donc exécutées seulement quand on sort lettres d’un mot, etc).
de la boucle).
# parcourt les entiers de la liste, calcule la somme
s = 0
Bornes incohérentes En cas d’incohérence dans les bornes du range, la séquence est vide, la
for e in [1, 4, 5, 0, 9, 1] :
boucle est donc ignorée, et l’on passe directement aux instructions suivantes. Par exemple :
s+=e
# de 200 à 210 avec un pas négatif, séquence vide, n’affiche rien print(s) # affichage en sortie de boucle
for k in range(200, 210, -2) : # parcourt les lettres de la liste, affiche 1 par ligne
print(k) for e in ["a", "e", "i", "o", "u", "y"]:
print(e)
# de 110 à 100 avec un pas positif, séquence vide, n’affiche rien # parcourt les lettres du mot, affiche 1 par ligne
for k in range(110,100,2) : for e in "python":
print(k) print(e)

51 52
1.12. Boucle inconditionnelle : for 1.13. Listes avancées

Algorithmes sur les listes La boucle for permet ainsi d’écrire des programmes intéressants pour >>> liste = [1,2,3,4,5]
manipuler des listes : trier une liste pour mettre ses éléments dans l’ordre ; chercher l’élément minimum >>> for i in liste :
ou maximum d’une liste ; compter le nombre d’occurrences d’un éléments donné dans une liste (combien print(i)
de fois il apparaît dans la liste) ; etc. (cf exercices de TD et TP) [Link](i)

# affichage produit
1.11.4 Très important : itération et modification
1
Attention ! Ne jamais modifier la variable de boucle dans le corps d’une boucle for ! Quoi qu’il 3
arrive dans le corps de la boucle, la variable de boucle (celle qui parcourt la séquence ou la structure 5
itérable) prend la valeur suivante (l’entier suivant de la séquence, l’élément suivant de laliste ou
autre structure itérable) à chaque nouvelle étape de la boucle. >>> liste
[2, 4]

Exemple (ce qu’il ne faut pas faire) Ce programme affiche les entiers 1,2,3,4 (un entier par Le comportement obtenu n’est pas ce qu’on attendait : seul un entier sur 2 est affiché et supprimé
ligne), c’est-à-dire qu’il parcourt la séquence générée par range(1,5). La modification de la variable de la liste. En effet, il ne faut jamais modifier la structure (ici la liste) en même temps qu’on la
i dans le corps de la boucle est immédiatement écrasée quand i prend la valeur suivante de la parcourt.
séquence avant de recommencer les instructions du corps de la boucle. Vous pouvez exécuter ce
programme dans Python Tutor pour mieux visualiser.
1.12 Listes avancées
for i in range(1, 5) :
print(i) 1.12.1 Fonction map
i = i*2
La fonction map() permet d’appliquer une fonction à tous les éléments d’une liste, et d’obtenir
la liste de tous les résultats. Le résultat est de type map, qu’il faut convertir en liste. On peut
Exemple corrigé (avec un while) Le programme ci-dessus est mauvais. Il ne faut jamais (jamais !) utiliser en paramètre le nom d’une fonction existante, ou bien une fonction anonyme avec lambda.
modifier le compteur de boucle dans un for. Dans cet exemple il vaudrait mieux écrire une boucle Les fonctions anonymes peuvent aussi servir à combiner plusieurs fonctions. (Voir les exemples ci-
while dans laquelle on peut multiplier i par 2 à chaque itération (il faudra initialiser i avant dessous.)
le while, et la condition du while devra spécifier la valeur maximale souhaitée). Cette version fonctionne
>>> list(map(len,["alex","cyril","elsa"]))
et affiche les entiers 1,2,4 (un par ligne).
[4, 5, 4]
i=1 >>> list(map([Link],[1,4,9,16]))
while i<5: [1.0, 2.0, 3.0, 4.0]
print(i) >>> list(map(lambda x:x**2,[1,4,9,16]))
i=i*2 [1, 16, 81, 256]
>>> list(map(lambda x:int([Link](x)),[1,4,9,16]))
[1, 2, 3, 4]
Exemple corrigé (avec un for) Avec une boucle for, il suffit de se rendre compte qu’on parcourt en
fait les puissances de 2, et d’écrire la version suivante, qui itère sur l’exposant, et affiche les 3 1.12.2 Compréhension de listes
premières puissances de 2 (en partant de puissance 0), donc 1, 2, 4.
Python offre une syntaxe abrégée pour manipuler les listes : la compréhension de listes. C’est
for i in range(3): une syntaxe plus concise pour écrire une boucle for qui crée une liste. Cela permet par exemple
print(2**i) de réécrire la fonction map. Quelques exemples :

>>> [x**2 for x in range(10)] # carres des entiers de 0 a 9


[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> prenoms = ["alex","cyril","elsa"]
Attention : ne jamais modifier la structure pendant qu’elle est parcourue !
>>> l = [len(x) for x in prenoms]
[4, 5, 4]
Exemple Dans l’exemple ci-dessous, on définit une liste de 5 entiers, puis on écrit une boucle >>> ["a" in x for x in prenoms]
qui affiche chaque élément puis le supprime de la liste. [True,False,True]

53 54
1.14. Fonctions: compléments 1.14. Fonctions : compléments

Exercice bonus : essayer d’écrire les fonctions du TD sur les boucles en un minimum d’ins- Exemple Par exemple cette fonction calcule et renvoie à la fois le quotient et le reste d’une
tructions en utilisant des compréhensions de listes (à éviter en général dans un vrai programme, division entière.
dans un souci de lisibilité).
def division(a,b) :
# renvoie le quotient et le reste
# de la division de a par b
1.13 Fonctions : compléments
quotient=a//b
reste= a%b
1.13.1 Le mot-clé None
return quotient, reste
Procédures Il existe une valeur constante en Python qui s’appelle None. Cela correspond à"rien",
"aucune valeur". Lorsqu’une fonction n’a pas d’instruction return, elle renvoie la valeur None. # programme principal
q,r = division(22,5)
def dit_bonjour(): print("q=", q, "et r=", r)
print("Bonjour!")
print("Bienvenue") 1.14.3 Fonction avec des paramètres optionnels
On a déjà vu plusieurs fonctions avec des paramètres optionnels : print (paramètres sep et
# pas de return Affichage obtenu au lancement du module :
end) ; range (paramètres deb et pas).
# programme Principal Bonjour!
test=dit_bonjour() Bienvenue.
print("Test vaut", test) Test vaut None Syntaxe de la définition d’une fonction à paramètres optionnels Pour rendre un argument
optionnel lors de la définition d’une fonction, il faut ajouter après le nom de l’argument le signe
= suivi de la valeur par défaut. Ci-dessous arg_opt est un argument optionnel de la fonction
Initialisation Le mot-clé None peut aussi servir à initialiser une variable lorsque l’on ne sait pas (valeur par défaut précisée), alors que arg1 n’est pas optionnel (pas de valeur par défaut précisée).
encore précisément quelle valeur on souhaite lui attribuer. Attention, None n’est pas une chaîne
de caractères en Python, donc il ne faut pas de guillemets ! # syntaxe standard d’une fonction avec argument optionnel
def nom_fonc(arg1, arg_opt=valeur_par_defaut):
reponse=None # on n’a pas encore de reponse instructions
while reponse!="non":
x=float(input("Veuillez entrer un nombre:"))
print("Le carré de ce nombre est:", x*x) Exemple La carte de MisterPizza comporte de multiples saveurs de pizzas, chacune pouvant être
reponse=input("Voulez-vous recommencer?") commandée en taille normale au prix de 9 euros, ou en taille maxi au prix de 12 euros. Latrès grande
print("Terminé") majorité des clients choisit des pizzas de taille normale, on veut donc que ce soit la valeur par défaut
si rien n’est précisé. Dans ce cas on peut utiliser un argument optionnel taillequi a pour valeur
par défaut "normale".
1.14.2 Fonction avec plusieurs valeurs de retour
def affiche_pizza(saveur, taille="normale"):
On a vu qu’une fonction pouvait ne rien renvoyer. Une fonction peut aussi renvoyer plus d’une
""" Affiche saveur, taille et prix de la pizza
valeur. Dans ce cas, quand on l’appelle, il faut affecter le retour dans le bon nombre de variables. Par
"""
exemple la fonction ci-dessous calcule et renvoie à la fois le quotient et le reste de la division de a
print("Pizza", saveur, "taille:", taille)
par b. Le programme principal affecte donc son retour dans 2 variables.
if taille=="normale":
prix=9
Syntaxe La syntaxe générale est la suivante : elif taille=="maxi":
prix=12
# Syntaxe (dans le corps de la fonction) pour renvoyer N valeurs print("Prix", prix, "euros.")
return valeur1, valeur2, ... , valeurN
Syntaxe de l’appel d’une fonction à paramètres optionnels Quand on appelle une fonction à
# Syntaxe pour récupérer les N valeurs de retour lors d’un appel paramètres optionnels, on peut préciser une valeur pour le(s) paramètre(s) optionnel(s), ou bien
var1, var2, ... , varN = nom_fonction(arguments) l’omettre et dans ce cas il(s) reçoi(ven)t leur(s) valeur(s) par défaut (spécifiées dans la définition

55 56
1.14. Fonctions: compléments 1.14. Fonctions : compléments

de la fonction). Si on reprend la fonction de l’exemple ci-dessus, voici comment l’appeler, en


précisant ou pas la valeur du paramètre optionnel. >>> affiche_pizza("Reine", "maxi", True)
Pizza Reine , taille: maxi
>>> affiche_pizza("4 fromages") Prix 12 euros ( 78.71 francs).
Pizza 4 fromages taille: normale
Prix 9 euros. >>> affiche_pizza("4 saisons", True)
>>> affiche_pizza("4 fromages", "maxi") Erreur car True est pris pour la taille (2eme arg.)
Pizza 4 fromages taille: maxi
Prix 12 euros.
Arguments nommés Pour résoudre ce problème, il faut nommer les arguments, afin de spécifierde
>>> affiche_pizza("Reine", "normale")
quel argument on reçoit la valeur. En effet, lors d’un appel de fonction, on peut préciser lenom
Pizza Reine taille: normale
de l’argument concerné par une valeur, comme ceci :
Prix 9 euros.
>>> affiche_pizza("4 fromages", afficheF=True)
Définition d’une fonction avec plusieurs paramètres optionnels MisterPizza souhaite parfois
afficher le prix en Francs, lorsque le client est âgé, mais il s’agit d’une situation peu fréquente. On Dans cet appel on a 2 types d’arguments :
peut donc rajouter un autre paramètre optionnel afficheF de type booléen, faux par défaut, qui
• La chaîne de caractères "4 fromages" est un argument non nommé, ou argument positionnel :
précise s’il faut afficher le prix en francs ou euros.
c’est sa position qui détermine à quel argument correspond cette valeur (ici la valeur est en 1e
def affiche_pizza(saveur, taille="normale", afficheF=False): position et sera donc affectée dans le 1e argument, à savoir saveur)
""" Affiche saveur, taille et prix de la pizza
• afficheF=True est un argument nommé : c’est le nom qui détermine à quel argument
"""
correspond la valeur qui suit (ici la valeur True, en 2e position mais nommée, est donc
print("Pizza", saveur, ", taille: ", taille)
affectée à l’argument afficheF, en 3e position, ce qui permet de ne pas spécifier la valeur du
if taille=="normale":
2e argument, taille)
prix=9
elif taille=="maxi": Pour que cela fonctionne, les arguments non-nommés doivent toujours être tous avant les
prix=12 arguments nommés dans l’appel. L’ordre des arguments nommés ensuite n’est pas déterminant,
if afficheF: seule compte leur position (tant qu’ils sont après les arguments non-nommés).
prixFrancs=round(prix*6.55957, 2)
print("Prix", prix, "euros (", prixFrancs, " F).") Exemples d’appels
else:
print("Prix", prix, "euros.") >>> affiche_pizza("4 fromages", afficheF=True)
Pizza 4 fromages , taille: normale
Appel d’une fonction avec plusieurs paramètres optionnels Les valeurs des paramètres sont Prix 9 euros ( 59.04 francs).
affectées dans l’ordre où elles sont reçues. Pour appeler la fonction précédente, qui a deux
paramètres optionnels, on a donc un problème dans le cas où on veut spécifier le 3e argument (prix >>> affiche_pizza("4 fromages", taille="maxi", afficheF=True)
en francs) mais pas le 2e (taille normale). En effet la valeur du 2e argument étant omise, c’est la Pizza 4 fromages , taille: maxi
valeur qu’on a donnée pour le 3e (booléen True) qui est affectée dans le 2e argument (variable Prix 12 euros ( 78.71 francs).
taille). Cela déclenche une erreur car la valeur True ne correspond à aucune des 2 valeurs
possibles (dans le if), donc la variable prix ne reçoit pas de valeur, ce qui empêche de l’afficher >>> affiche_pizza("Chorizo", taille="maxi", True)
ensuite. Erreur: il y a un argument non-nommé après un argument nommé

>>> affiche_pizza("4 fromages") >>> affiche_pizza("Reine", afficheF=True, taille="maxi")


Pizza 4 fromages taille: normale Pizza Reine , taille: maxi
Prix 9 euros. Prix 12 euros ( 78.71 francs).

>>> affiche_pizza("4 fromages", "maxi") >>> affiche_pizza("Chorizo", True, taille="maxi")


Pizza 4 fromages taille: maxi Erreur car taille définie 2 fois
Prix 12 euros. (True pris pour taille car 2ème arg. non-nommé)

57 58
1.14. Fonctions : compléments 1.15. Dictionnaires

L’exemple de la fonction print En fait, nous avions déjà rencontré une fonction avec des Docstring sur une fonction existante En cas de doute sur le principe d’une fonction existante, vous
arguments optionnels nommés : la fonction print pouvez utiliser la commande help pour afficher sa documentation. Par exemple si on ne se rappelle
plus si les bornes sont incluses lors de la génération d’un entier pseudo-aléatoire.
>>> print("Mon age est", 18)
>>> print("Mon age est", 18, sep="égal à") >>> import random
>>> print("Mon age est", 18, end=".") >>> help([Link])
>>> print("Mon age est", 18, sep=":", end=".") Help on method randint in module random:
randint(a, b) method of [Link] instance
sep et end sont des arguments optionnels de print. Par défaut, sep vaut " " (espace) et end Return random integer in range [a, b], including both end points.
vaut " n" (re\tour à la ligne). Note : sep et end doivent toujours être nommés car la fonction print a
un nombre variable d’arguments non-nommés (les valeurs à afficher), donc on ne peut pas Docstring et Help sur fonction avec paramètres optionnels La documentation affichée pour
déterminer la position de ces arguments. notre fonction précédente montre bien le paramètre optionnel taille et sa valeur par défaut.

>>> help(affiche_pizza)
1.14.4 Utilisation de Docstring
Help on function affiche_pizza in module main :
Une docstring est une chaîne de caractères, encadrée par des triples guillemets, placée au tout début affiche_pizza(saveur, taille=’normale’)
d’une fonction, et qui permet de décrire cette fonction. Affiche saveur, taille et prix de la pizza

Syntaxe générale 1.14 Dictionnaires


def nom_fonction(argument1, argument2, ...): Tout comme une liste, un dictionnaire permet de sauvegarder en mémoire plusieurs valeurs de
""" docstring types quelconques. Cependant, contrairement à une liste, les valeurs d’un dictionnaire ne sont
""" pas stockées de manière ordonnée, mais sont associées à des clés. On accède donc aux éléments par
instructions de la fonction leur clé et pas par leur indice. Chaque clé est unique.
On peut l’afficher grâce à la commande help, qui prend en paramètre le nom de la fonction
(uniquement le nom, pas de parenthèse ni de paramètre) dont on veut obtenir la documentation : 1.14.1 Création

help(nom_fonction): Déclaration La syntaxe générale pour déclarer et initialiser un dictionnaire D contenant certaines
Help on function nom_fonction in module nom_module: paires clé-valeur est la suivante :
nom_fonction(argument1, argument2, ...) D = { cle1: valeur1, cle2: valeur2, ..., cleN: valeurN }
docstring de la fonction affichée ici
Exemple On veut créer un dictionnaire contenant la note moyenne de chaque étudiant dans
Exemple Si on spécifie la documentation au moment de la définition de la fonction, l’utilisateur de une certaine matière. Les clés de ce dictionnaire seront les noms des étudiants, et les valeurs seront
notre code pourra alors dans l’interpréteur (ou dans un programme) appeler l’instruction help leurs notes. Chaque valeur (note) est donc associée à un étudiant (clé). Deux étudiants peuvent avoir
pour afficher cette documentation. la même note, mais chaque étudiant ne peut avoir qu’une seule note (on suppose que chaque
prénom est unique dans la classe). Ci-dessous la variable notes est un dictionnaire contenant les
def division(a,b) : notes de deux étudiants. Les chaînes de caractères ‘nathan’ et ‘quentin’ sont les clés de ce
""" Renvoie le quotient et le reste dictionnaire. 12.0 et 15.5 sont les valeurs du dictionnaire. Les éléments du dictionnaire ne sont pas
de la division de a par b """ ordonnés : on n’y accède pas par un numéro (indice, position) mais par leur clé.
quotient=a//b
reste= a%b >>> notes = { ‘nathan’: 12.0, ‘quentin’: 15.5 }
return quotient, reste >>> notes
{’nathan’: 12.0, ’quentin’: 15.5}
>>> help(division)
Help on function division in module main : Types des clés et valeurs Les clés d’un dictionnaire ne peuvent être que de certains types. Dans
division(a, b) ce cours on se limitera aux entiers et aux chaînes de caractères. Par contre comme pour les listes, les
Renvoie le quotient et le reste valeurs dans un dictionnaire peuvent être de n’importe quel type, y compris de type dictionnaire.
de la division de a par b

59 60
1.15. Dictionnaires 1.15. Dictionnaires

pc_tp = { Vérifier l’existence d’une entrée Avant d’accéder à une valeur, on prendra donc l’habitude
‘ram’: 16, # val. de type int de toujours vérifier l’existence de la clé, avec l’opérateur in comme pour les listes. Attention !
‘cpu’: 3.5, # val. de type float L’opérateur in vérifie l’existence d’une clé, et non pas d’une valeur.
‘portable’: False, # val. de type bool
# recherche d’une cle : ok
‘os’: ‘windows’, # val. de type str
‘ports’: [‘usb3.0’, ‘jack’, ‘ethernet’, ‘hdmi’], # val. de type list >>> prix = {‘asus’: 450, ‘alienware’: 1200, ‘lenovo’: 680}
‘carte_graphique’: { # val. de type dict >>> ‘asus’ in prix
‘vram’: 4, True
‘nom’: ‘gtx970’, >>> ‘toshiba’ in prix
‘bus’: 256 False
} # recherche d’une valeur : echec
} >>> 1200 in prix
False

Exemple Si on veut stocker les moyennes des étudiants dans plusieurs matières, on peut avoir un
dictionnaire de dictionnaires, contenant soit un dictionnaire par étudiant (dont les clés seront les 1.14.3 Modification d’un dictionnaire
matières), soit un dictionnaire par matière (dont les clés seront les étudiants). Ajout d’une entrée Pour rajouter une nouvelle entrée (une paire clé :valeur) dans un dictionnaire
# un dico par etudiant existant, il suffit d’utiliser l’opérateur = (affectation) pour associer la valeur à la clé, comme suit. On
notes_e = { peut donc faire une affectation avec une clé qui n’existe pas encore dans le dictionnaire, pour l’y
’nathan’: {’maths’:15, ’info’: 17}, ajouter.
’quentin’: {’info’:13, ’bio’:18} >>> D = {} # crée un dictionnaire vide
} >>> D
# un dico par matière {}
notes_m = { >>> D[‘a’] = 1 # ajout de la nouvelle entrée
’maths’: {’nathan’:15}, >>> D
’info’: {’nathan’:17,’quentin’:13}, {‘a’: 1}
’bio’: {’quentin’:18}

}
Modification d’une entrée Pour modifier une entrée déjà présente dans le dictionnaire (c’est-à-
dire modifier la valeur d’une clé présente dans le dictionnaire), on procède de la même manière, en
1.14.2 Utilisation d’un dictionnaire utilisant aussi l’affectation =. L’ancienne valeur de cette clé est écrasée, remplacée par la nouvelle
Accès aux valeurs L’accès à une valeur du dictionnaire se fait non pas par sa position (indice), mais valeur.
grâce à sa clé. Par exemple dans notre premier dictionnaire de notes, on peut utiliser la chaînede
>>> D
caractères ‘quentin’ (la clé) pour accéder à la valeur qui y est associée dans le dictionnaire notes
{’a’: 1}
(la note de Quentin, 15.5). Les dictionnaires sont aussi appelés listes associatives, car ils permettent
>>> D[‘a’] = 3
d’associer à chaque clé une valeur de type quelconque.
>>> D
>>> notes = {‘nathan’: 12.0, ‘quentin’: 15.5} {‘a’: 3}
>>> notes[‘quentin’] >>> D[’a’]
15.5 3

Erreurs de clé Attention, si on tente d’accéder à une entrée qui n’existe pas dans le dictionnaire, le Suppression d’une entrée L’opérateur del permet de supprimer une association d’un diction-
programme renvoie une erreur de clé (KeyError). naire. Comme pour l’accès aux valeurs, il faut que la clé spécifiée existe, sinon on déclenche une
erreur de clé.
>>> lettres = {‘a’: 103, ‘b’: 8, ‘e’: 150}
>>> lettres[‘k’] # erreur, pas de clé ’k’ dans le dico >>> D = {‘a’: 1, ‘b’: 2, ‘c’: 3}
KeyError: ’k‘ >>> del D[‘a’]
>>> lettres[‘u’] = lettres[‘u’] + 1 # erreur, pas de clé ’u’ >>> D
KeyError: ‘u‘ {‘b’: 2, ‘c’: 3}

61 62
1.15. Dictionnaires 1.15. Dictionnaires

>>> del D[‘j’] # erreur, pas de clé ’j’ 1.14.5 Un exemple détaillé
KeyError: ‘j‘
Dans l’exemple ci-dessus on veut compter chaque lettre dans un mot ou une liste. La fonction
reçoit la lettre à compter et le dictionnaire de compteurs, qu’elle met à jour en conséquence (la
1.14.4 Parcourir un dictionnaire fonction ne renvoie pas le dictionnaire, mais a pour effet de bord de le modifier). Le programme
Itération avec for. La boucle for peut être utilisée pour parcourir toutes les clés d’un dictionnaire (qui principal initialise le dictionnaire de compteurs, parcourt la chaîne de caractères, et appelle cette
permettent d’accéder aux valeurs associées). fonction sur chaque lettre lue.

# affichage des associations clé:valeur, une par ligne # fonction qui reçoit la lettre à compter
for key in D: # et le dictionnaire de compteurs, qu’elle met à jour
print(‘La clé’, key, ‘a pour valeur: ‘, D[key]) # pas de valeur de retour, modif du dico par effet de bord
def vu_lettre(l,cpts):
# affichage des dates d’anniversaire # verification d’existence
dates_naissance={’ingrid’:[12,6,1995],’marc’:[27,8,1996],’brice’:[11,10,1995]} if l in cpts:
# la variable nom parcourt les clés du dictionnaire (les prénoms) # si existe, incrementation
for nom in dates_naissance : cpts[l] = cpts[l] + 1
# date : valeur associée au nom, la liste représentant la date de naiss. else:
date = dates_naissance[nom] # sinon, initialisation
print(nom, ’fetera son anniversaire le’,date[0],’/’,date[1]) cpts[l] = 1
Ce programme affiche les lignes suivantes :
# programme principal
ingrid fetera son anniversaire le 12 / 6 phrase = "bonjour a tous"
marc fetera son anniversaire le 27 / 8 # initialiser un dictionnaire vide de compteurs
brice fetera son anniversaire le 11 / 10 cpts = {}
for lettre in phrase:
Liste des clés et des valeurs La fonction keys() permet d’accéder aux clés d’un dictionnaire, # appel de la fonction sur chaque lettre vue
dans une structure de type dict_keys. De même la fonction values() permet d’accéder aux vu_lettre(lettre,cpts)
valeurs d’un dictionnaire, dans une structure de type dict_values. Ces deux structures ne sont # affichage du dictionnaire de compteurs
pas indexables, mais on peut les convertir en liste avec la fonction list(). Par exemple : print(cpts)
>>> dico = {’a’:1,’b’:0,’c’:0,’d’:0,’e’:1} L’exécution de ce programme affiche le dictionnaire de compteurs ’b’ :1,’o’ :3,’n’ :1,’j’ :1,’u’ :2,’r’ :1,’
>>> dk = [Link]() ’ :2,’a’ :1,’t’ :1,’s’ :1. Seuls les caractères qui ont été rencontrés ont été ajoutés dans le dictionnaire (y
>>> dk compris l’espace).
dict_keys([’a’, ’b’, ’c’, ’d’, ’e’])
>>> dk[1]
1.14.6 Copie de dictionnaires
Traceback (most recent call last):
File "<stdin>", line 1, in <module> Affectation Comme dans le cas des listes, l’affectation d’un dictionnaire vers une variable ne fait
TypeError: ’dict_keys’ object does not support indexing que référencer le même dictionnaire par un nouvel identificateur. Si on modifie l’un, on modifie
>>> [Link]() aussi l’autre.
dict_values([1, 0, 0, 0, 1])
>>> D = {1: 10, 2: 20, 3: 30}
>>> lc = list([Link]()) >>> E = D
>>> lc >>> E[5] = 50
[’a’, ’b’, ’c’, ’d’, ’e’] >>> E
>>> lv = list([Link]()) {1: 10, 2: 20, 3: 30, 5: 50}
>>> lv >>> D
[1, 0, 0, 0, 1] {1: 10, 2: 20, 3: 30, 5: 50}
>>> lv[1]
0 Copie Pour créer une copie de surface d’un dictionnaire, on utilise dict().

63 64
1.16. Introduction aux fichiers 1.16. Introduction aux fichiers

>>> F = dict(D) # création d’une copie de D nommée F Lecture de tout le texte On peut lire en une seule fois tout le contenu du fichier et le stocker
>>> F[6] = 60 # ajout d’une clé dans F dans une chaîne de caractères, qui contiendra le texte entier.
>>> F # F a été modifie
texte = [Link]()
{1: 10, 2: 20, 3: 30, 5: 50, 6: 60}
>>> D # mais pas D
Lecture de toutes les lignes On peut aussi lire en une fois toutes les lignes du fichier et les stocker
{1: 10, 2: 20, 3: 30, 5: 50}
dans une liste de chaînes de caractères (une chaîne par ligne). Après cette instruction, lignes est
>>> G = F # création d’un 2e nom pour le même dico
une liste qui contient toutes les lignes du fichier. On peut y accéder une par une, par exemple
>>> G[7] = 1 # ajout d’une clé dans G
lignes[0] contient la première ligne, etc.
>>> G # G a été modifié
{1: 10, 2: 20, 3: 30, 5: 50, 6: 60, 7: 1} lignes = [Link]()
>>> F # mais F aussi
{1: 10, 2: 20, 3: 30, 5: 50, 6: 60, 7: 1} Lecture itérative par ligne Enfin on peut aussi lire le fichier ligne par ligne de manière itérative,
avec une boucle for. Le programme ci-dessous lit une ligne après l’autre dans le fichier et les affiche
au fur et à mesure. On ne stocke donc jamais l’intégralité du fichier en mémoire, seulement une ligne
1.15 Introduction aux fichiers à la fois.
for ligne in f:
Jusqu’à présent, nous avons utilisé input() et print() pour lire les entrées du programme,
print(ligne) # affiche une ligne du fichier
et afficher les résultats obtenus. Mais parfois, les données d’entrée sont stockées dans un fichier et
on aimerait pouvoir y accéder directement, sans les saisir manuellement au clavier (surtout quand
Exemple Soit le fichier « [Link] » qui contient les entiers suivants (un par ligne) : 15 18 30
il y en a beaucoup, ou quand on teste plusieurs fois un programme). Souvent, il est aussi utile de
55 16 3 12 13. Le programme ci-dessous calcule la somme de ces entiers.
sauvegarder les résultats d’un programme dans des fichiers afin de pouvoir y accéder plus tard (par
ex : sauvegarde d’une partie dans un jeu vidéo). En Python, il est très facile de lire et d’écrire des fichier = open(‘[Link]’) # ouvrir le fichier en lecture
données dans des fichiers. somme = 0 # initialiser la somme
for nombre in fichier: # nombre parcourt les lignes une par une
# nombre est une chaîne, ne pas oublier de la convertir en entier !
1.15.1 Ouverture d’un fichier texte
somme = somme + int(nombre)
Ouvrir un fichier Avant de commencer la lecture d’un fichier, il faut d’abord l’ouvrir. Ouvrir un # après la fin de la boucle de calcul, afficher une seule fois la somme
fichier veut simplement dire que l’on crée une variable qui permet de le manipuler. La fonction print(somme)
open() est utilisée pour ouvrir un fichier. Par exemple pour ouvrir un fichier appelé «[Link]», on # ne pas oublier de fermer le fichier après utilisation
écrit : [Link]()

>>> f=open(‘[Link]’) 1.15.3 Écriture dans un fichier texte


>>> f
Ouverture en mode écriture Quand un fichier est ouvert en mode lecture, on ne peut que le lire
<_io.TextIOWrapper name=’[Link]’ mode=’r’ encoding=’UTF-8’>
mais pas le modifier. Pour pouvoir écrire dans un fichier, il faut l’ouvrir en mode écriture. Si le fichier
n’existe pas encore il est créé (on ne déclenche donc pas d’erreur). On remarque que le mode vaut
Mode d’ouverture Par défaut, open() ouvre un fichier en mode lecture (mode = ’r’ pour ’read’), c’est- maintenant ’w’ pour ’write’, ce qui indique qu’on peut écrire dans ce fichier.
à-dire qu’on peut lire son contenu mais on ne peut pas le modifier. Il faut donc que le fichier existe.
>>> f = open(’[Link]’,’w’)
Si on tente d’ouvrir un fichier inexistant en mode «lecture», on déclenche une erreur.
>>> f
<_io.TextIOWrapper name=’[Link]’ mode=’w’ encoding=’UTF-8’>
>>> f = open(’toto’) # le fichier ‘toto’ n’existe pas
Traceback (most recent call last):
File "<stdin>", line 1, in <module> Ouverture en mode ajout Si le fichier ouvert en mode «écriture» n’existe pas, il est créé (vide). Mais
IOError: [Errno 2] No such file or directory: ’toto‘ attention ! S’il existe déjà, tout son contenu est effacé. Pour pouvoir écrire à la suite du texte présent dans
un fichier déjà existant, il faut l’ouvrir en mode ’ajout’ (’append’).
>>> f = open(’[Link]’,’a’)
1.15.2 Lecture d’un fichier texte
>>> f
Une fois notre fichier texte ouvert, il existe plusieurs manières de lire son contenu. <_io.TextIOWrapper name=’[Link]’ mode=’a’ encoding=’UTF-8’>

65 66
1.16. Introduction aux fichiers 1.16. Introduction aux fichiers

Écriture La fonction permettant d’écrire dans un fichier texte est write(). Contrairement à # ouverture en écriture (création si inexistant, écrasement si existe)
print(), la fonction write() ne saute pas de ligne automatiquement. Elle écrit dans le fichier fichier = open(‘[Link]’, ‘w’)
exactement la chaîne de caractères reçue en argument. Pour sauter une ligne dans le fichier, il # 10 itérations pour les 10 puissances
faut écrire un saut de ligne manuellement avec le caractère spécial\n (voir d’autres caractères for i in range(0,10):
spéciaux dans le cours sur les chaînes de caractères). # il faut convertir l’entier en chaîne de caractères
# et passer a la ligne explicitement
[Link](‘ce texte sera écrit dans le fichier’)
[Link](str(2 ** i) + ‘\n’)
[Link](‘\n’) # ceci permet de passer à la ligne
# fin de la boucle, on peut fermer le fichier
[Link]()
Argument de write La fonction write() reçoit exactement un argument, qui doit obligatoire-
ment être une chaîne de caractères. Pour écrire un entier ou une valeur d’un autre type, il faut le convertir
en chaîne de caractères en utilisant str() et la concaténer à la chaîne à écrire.
>>> m = 12
>>> [Link]("m=",m) # on ne peut pas passer plusieurs arguments
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: write() takes exactly one argument (2 given)
>>> [Link](m) # on ne peut pas écrire un entier
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: write() argument must be str, not int
>>> s = "m="+str(m) # creation de la chaine a ecrire
>>> [Link](s) # ecriture : ok
4

Valeur de retour de write La fonction write() renvoie le nombre de caractères effectivement écrits
dans le fichier. Dans l’exemple ci-dessus on a écrit la chaîne "m=12" donc 4 caractères.

1.15.4 Fermeture
Une fois la lecture/écriture terminée, il faut fermer le fichier en utilisant la fonction close().
Une fois fermé, on ne peut plus lire ou écrire dans le fichier.

f = open(‘[Link]’)
# lecture iterative ligne par ligne
for ligne in f:
print(‘une ligne lue :’, ligne)
[Link]()

>>> [Link](’tata’)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: I/O operation on closed file.

Exemple La fonction suivante permet de sauvegarder les 10 premières puissances de 2 dans un


fichier texte nommé « [Link] » (une par ligne). Après exécution de ce programme, le fichier texte
[Link] contiendra donc les entiers suivants (un par ligne) : 1 2 4 8 16 32 64 128 256 512,
c”est-à-dire les puissances de 2 entre 20 et 29.

67 68

Vous aimerez peut-être aussi