L'objectif de ce tutoriel est de présenter une introduction à Python 3 à des étudiants ayant déjà des notions d'algorithmique et de programmation. Par exemple le fonctionnement des boucles $\mathtt{for}$ n'est pas expliqué mais on y étudie leur implémentation en Python.
La documentation officielle est disponible à l'adresse https://docs.python.org/fr/3/
Voici les différents points abordés dans ce tutoriel.
Ce tutoriel débute par une introduction (incomplète) au langage Python. Cette partie est consacrée aux notions de base pour prendre en main ce langage.
Types de données et opérations de base
Structures de données : listes, tuples, dictionnaires, ensembles
Tests et instructions conditionnelles
Boucles while et for
Procédures et fonctions
Importer un module
a=1
print(a)
1
a=1
print(a+1)
2
a=1
print("Si a=",a,"\nalors a+1=",a+1)
Si a= 1 alors a+1= 2
a=input("Rentrer la valeur de a :")
print(a)
Rentrer la valeur de a :12 12
Attention le résultat de la fonction $\mathtt{input}$ est toujours une chaîne de caractères (type $\mathtt{str}$).
a=1
type(a)
int
Notez que le booléen $\mathtt{True}$ prend la valeur $\mathtt{1}$ et le booléen $\mathtt{False}$ la valeur $\mathtt{0}$.
print(True+1)
2
Comme vu plus haut il n'est pas nécessaire de déclarer le type d'une variable avant de lui affecter une valeur. On peut bien évidemment utiliser des fonctions de conversion d'un type à l'autre.
a=int(input("Entrer la valeur de a :")) # notez la conversion en int
print(a+1)
Entrer la valeur de a :12 13
a=4
print(4/2)
2.0
La puissance s'obtient avec le symbole $\mathtt{**}$.
print(2**3)
8
Pour les entiers il existe aussi les fonctions de modulo $\mathtt{\%}$ et de division entière $\mathtt{//}$.
print(5%2)
print(5//2)
1 2
a=1
b=2
a, b = b, a
print("a=",a)
print("b=",b)
a= 2 b= 1
Les listes sont définies via le constructeur $\mathtt{[ ]}$. Le premier élément d'une liste est celui d'indice $\mathtt{0}$.
l = [0, 1, 2]
print("Liste entière :", l)
print("Deuxième élément de la liste", l[1])
Liste entière : [0, 1, 2] Deuxième élément de la liste 1
l = [0, 1, 2]
l[0] = "test"
print(l)
['test', 1, 2]
l1 = [0, 1]
l2 = [2]
print(len(l1))
print(len(l2))
2 1
La somme de deux listes est l'opération de concaténation.
l1 = [0, 1]
l2 = [2]
l = l1 + l2
print(len(l))
print(l)
3 [0, 1, 2]
Dans le même esprit on peut répliquer une liste avec l'opération $\mathtt{*}$. Ceci est bien pratique si l'on veut créer une liste d'une taille donnée.
print(3*['a','b'])
print(7*[0])
['a', 'b', 'a', 'b', 'a', 'b'] [0, 0, 0, 0, 0, 0, 0]
l = [0,1,2,3]
print(min(l))
print(max(l))
print(sum(l))
0 3 6
l1= [0,1,2]
l2= l1
ne va pas copier les valeurs de $\mathtt{l1}$ dans la liste $\mathtt{l2}$ mais donner deux noms différents à la même liste (c'est un pointeur). Ainsi, toute modification de $\mathtt{l1}$ va modifier $\mathtt{l2}$...
l1 = [0,1,2]
l2 = l1
l2[0] = 3
print(l2)
print(l1)
l1.append(4)
print(l1)
print(l2)
[3, 1, 2] [3, 1, 2] [3, 1, 2, 4] [3, 1, 2, 4]
Il y a une exception à cette règle : la concatenation.
l1 = [0,1,2]
l2 = l1
l2 = l2 + [3]
print(l2)
print(l1)
[0, 1, 2, 3] [0, 1, 2]
Pour copier les valeurs d'une liste on préférera l'utilisation de la méthode (notez la différence lors du recours à une méthode par rapport à une fonction) $\mathtt{copy}$
l1= [0,1,2]
l2= l1.copy()
l1 = l1 + [3]
print(l2)
[0, 1, 2]
l=[0,1,2]
l.append(3) # on ajoute 3 à la fin
print(l)
l.insert(0,-1) # on ajoute -1 en position 0
print(l)
del l[1] # on supprime l'élément en position 1
print(l)
l.remove(2) # on supprime le 2
print(l)
[0, 1, 2, 3] [-1, 0, 1, 2, 3] [-1, 1, 2, 3] [-1, 1, 3]
Il faut donc être particulièrement vigilant avec les indices lors des parcours de listes.
l = [0,1,2]
print(l[-1])
2
l = [0,1,2,3,4]
print(l[1:4])
# Un autre exemple
print(l[0:2])
# Le 0 étant le début de la liste est optionnel
print(l[:2])
# Idem pour l'indice de fin
print(l[:])
# On peut aussi modifier directement des tranches
l[:2] = ['a','b']
print(l)
[1, 2, 3] [0, 1] [0, 1] [0, 1, 2, 3, 4] ['a', 'b', 2, 3, 4]
l=['a','b','c','d']
print('a' in l)
print('e' in l)
print('e' not in l)
True False True
Si un élément est présent dans une liste on peut récupérer son indice avec la méthode $\mathtt{index}$.
l=['a','b','c','d']
print(l.index('c'))
2
l = [0,2,1,4,3]
l.sort()
print(l)
[0, 1, 2, 3, 4]
l = [0,2,1,4,3]
l.reverse()
print(l)
[3, 4, 1, 2, 0]
l = [0,2,1,4,3]
l2 = sorted(l)
print("Liste dans l'ordre croissant : ",l2)
l3 = sorted(l, reverse=True)
print("Liste dans l'ordre décroissant : ",l3)
Liste dans l'ordre croissant : [0, 1, 2, 3, 4] Liste dans l'ordre décroissant : [4, 3, 2, 1, 0]
Avec l'argument $\mathtt{key}$ on peut spécifier par rapport à quel élément on souhaite trier.
l = [(1,'b'), (3,'a'), (2,'c')]
print("Tri suivant le 1er élément : ",sorted(l, key= lambda x : x[0]))
print("Tri suivant le 2eme élément : ",sorted(l, key= lambda x : x[1]))
Tri suivant le 1er élément : [(1, 'b'), (2, 'c'), (3, 'a')] Tri suivant le 2eme élément : [(3, 'a'), (1, 'b'), (2, 'c')]
m = [[1,2,3],[4,5,6]]
print(m)
print(m[1][2])
[[1, 2, 3], [4, 5, 6]] 6
t = (1, 2, 3)
type(t)
tuple
t = 1, 2
type(t)
tuple
t = 1,
type(t)
tuple
On peut récupérer ces éléments en utilisant leurs indices ou la syntaxe suivante
t = (1, 2, 3, 4)
a= t[0]
print(a)
# Si l'on veut donner un nom à tous les éléments
a, b, c, d = t
print(b)
# Si l'on ne veut que certains éléments
a, *l, d = t
print(a,l,d)
1 2 1 [2, 3] 4
t = (1, 2, 3, 4)
print(t[0])
print(t[:3])
t2 = t + (5,6)
print(t2)
print(3 in t2)
print(t2.index(3))
1 (1, 2, 3) (1, 2, 3, 4, 5, 6) True 2
t = (1,2)
t[0]=2
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-35-6b0b18175a0f> in <module> 1 t = (1,2) ----> 2 t[0]=2 TypeError: 'tuple' object does not support item assignment
t = (1,2)
t.append(3)
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-36-78f6a6297cdf> in <module> 1 t = (1,2) ----> 2 t.append(3) AttributeError: 'tuple' object has no attribute 'append'
t = 1, 2, 3
print(t)
print(list(t))
l = [4,5,6]
print(l)
print(tuple(l))
(1, 2, 3) [1, 2, 3] [4, 5, 6] (4, 5, 6)
d = {'b':2, 'c':3, 'a':1}
print(d)
{'b': 2, 'c': 3, 'a': 1}
print(d['a'])
1
Là encore on peut mélanger plusieurs types.
d = { 1:2 , 'a':1, 'b':(1,2)}
print(d[1])
print(d['b'])
2 (1, 2)
d = {'b':2, 'c':3, 'a':1}
print(d)
d['c']=0
print(d)
d['d']=8
print(d)
{'b': 2, 'c': 3, 'a': 1} {'b': 2, 'c': 0, 'a': 1} {'b': 2, 'c': 0, 'a': 1, 'd': 8}
d = {'b':2, 'c':3, 'a':1}
print(d)
d2 = d.copy()
del d2['b']
print(d)
print(d2)
{'b': 2, 'c': 3, 'a': 1} {'b': 2, 'c': 3, 'a': 1} {'c': 3, 'a': 1}
Regardez la différence entre le résultat obtenu et le résultat suivant.
d = {'b':2, 'c':3, 'a':1}
print(d)
d2 = d # ici d n'est pas copié : une modification de d2 entraine une modification de d
del d2['b']
print(d)
print(d2)
{'b': 2, 'c': 3, 'a': 1} {'c': 3, 'a': 1} {'c': 3, 'a': 1}
d = {'b':2, 'c':3, 'a':1}
print(d.keys())
print(d.items())
dict_keys(['b', 'c', 'a']) dict_items([('b', 2), ('c', 3), ('a', 1)])
Ce sont des itérables : on peut donc les utiliser dans une boucle $\mathtt{for}$
d = {'b':2, 'c':3, 'a':1}
for k in d.keys():
print(d[k])
2 3 1
Symmétriquement la fonction $\mathtt{dict}$ construit un dictionnaire à partir d'une liste de couples (clés, valeurs).
l = [('a',1), ('b',2), ('c',3)]
d = dict(l)
print(d)
{'a': 1, 'b': 2, 'c': 3}
En $\texttt{Python}$ comme en mathématiques un ensemble est non ordonné. Il est défini par des accolades.
V = {1, 2, 3}
W = {3, 1, 2}
print(V == W)
True
On peut tester si un élément est présent ou non dans un ensemble
V = {1, 2, 3}
print(1 in V)
print(2 not in V)
True False
On peut ajouter et enlever un élément dans un ensemble
V = {1, 2, 3}
V.add(4)
print(V)
V.remove(2)
print(V)
{1, 2, 3, 4} {1, 3, 4}
On peut aussi réaliser les différentes opérations ensemblistes
V = {1,2,3}
W = {3,4,5}
print("Union : ",V.union(W))
print("Intersection : ",V.intersection(W))
print("Difference : ",V.difference(W))
Union : {1, 2, 3, 4, 5} Intersection : {3} Difference : {1, 2}
a=1
a+1 == 2
True
Il peut être important de remarquer que pour des nombres le type n'importe pas lors du test.
print(1 == 1.0)
print(type(1) == type(1.0))
True False
Chacune de ces instructions est suivie du symbole "$\mathtt{:}$" qui débute le champ d'action de l'instruction conditionnelle. Le champ d'action est délimité par l'indentation : en Python il n'y a pas de mot clé de fin d'instruction ! Cela sera aussi valable pour les boucles ou les fonctions. Regardez bien la différence entre les deux programmes suivants.
a=1
if a%2 == 0:
a=a+1
print(a)
# Rien ne se passe car "le print est dans le if"
a=1
if a%2 == 0:
a=a+1
print(a)
# Le programme affiche a car "le print n'est pas dans le if"
1
Exemples d'utilisation
# L'utilisateur entre un nombre, le programme affiche la parité de ce nombre
a = int(input("Entrez un nombre :"))
if (a%2) == 0:
print("Vous avez entré un nombre pair")
else:
print("Vous avez entré un nombre impair")
Entrez un nombre :15 Vous avez entré un nombre impair
# Le même programme qui affiche un message différent si le nombre entré est 5
a = int(input("Entrez un nombre :"))
if a==5:
print("C'est mon nombre préféré")
else:
if (a%2) == 0:
print("Vous avez entré un nombre pair")
else:
print("Vous avez entré un nombre impair différent de 5")
Entrez un nombre :15 Vous avez entré un nombre impair différent de 5
# Le même programme en utilisant elif
a = int(input("Entrez un nombre :"))
if a==5:
print("C'est mon nombre préféré")
elif (a%2) == 0:
print("Vous avez entré un nombre pair")
else:
print("Vous avez entré un nombre impair différent de 5")
Entrez un nombre :15 Vous avez entré un nombre impair différent de 5
Comme pour les instructions conditionnelles, la boucle démarre après le symbole "$\mathtt{:}$" et concerne toutes les lignes indentées.
i=0
while i<=5:
print(i)
i=i+1
print("la boucle est terminée") # cette ligne n'est pas indentée donc ne fait pas partie de la boucle
0 1 2 3 4 5 la boucle est terminée
# Le même programme mais en n'affichant que les nombres pairs
i=0
while i<=5:
if i%2 == 0:
print(i) # cette ligne est dans le if
i=i+1 # cette ligne n'est pas dans le if mais est bien dans la boucle while
print("on a affiché les nombres pairs entre 0 et 5")
0 2 4 on a affiché les nombres pairs entre 0 et 5
La première utilisation est classique.
for i in [0,1,2,3,4]:
print(i,end=" ") # le paramètre end évite ici les sauts de ligne
0 1 2 3 4
Il est bien sûr inevisageable de taper les listes $[0,1,2,3,4]$ à la main. Pour cela on va utiliser la fonction $\mathtt{range}$. Cette fonction produit une suite. Même si ce n'est pas tout à fait le cas on peut avoir en tête que $$ \mathtt{range}(N) = [0, 1, 2, \dots, N-1].$$ Donc $\mathtt{range}(N)$ contient $N$ éléments : le paramètre de fin est exclu. On peut préciser le paramètre de début. Alors $$ \mathtt{range}(\text{début}, \text{fin}) = [\text{début}, \text{début}+1, \dots, \text{fin}-1].$$ S'il y a trois arguments, le troisième est le pas de l'itération.
print("Utilisation de range avec un paramètre")
for i in range(5):
print(i,end=" ")
print('\n')
print("Utilisation de range avec deux paramètres")
for i in range(2,7):
print(i,end=" ")
print('\n')
print("Utilisation de range avec trois paramètres")
for i in range(2,12,2):
print(i,end=" ")
print('\n')
print("Le pas peut être négatif. Observez bien le résultat.")
for i in range(8,2,-1):
print(i,end=" ")
Utilisation de range avec un paramètre 0 1 2 3 4 Utilisation de range avec deux paramètres 2 3 4 5 6 Utilisation de range avec trois paramètres 2 4 6 8 10 Le pas peut être négatif. Observez bien le résultat. 8 7 6 5 4 3
Ainsi, une possibilité pour parcourir une liste est :
l = [5,3,4,1,2]
for i in range(len(l)):
print(l[i], end=" ")
5 3 4 1 2
En fait la boucle $\mathtt{for}$ itère sur les éléments présents dans la liste (ou le tuple ou la chaîne de caractères ou la suite fournie par $\mathtt{range}$) donnée en paramètre et pas sur un compteur. Le code précédent peut donc être simplifié.
# Itération sur une liste
l = [5,3,4,1,2]
for i in l:
print(i, end=" ")
print()
# Itération sur une chaîne de caractères
s = "Test"
for i in s:
print(i, end="-") # on sépare les caractères par des -
print()
# Itération sur un tuple
t = 1, [2,3], 'a'
for i in t:
print(i, end=" ")
5 3 4 1 2 T-e-s-t- 1 [2, 3] a
l = [i for i in range(10)]
print(l)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
l = [x**2 for x in range(10)]
print(l)
# On extrait un élément sur deux de la liste l
l2 = [l[i] for i in range(len(l)) if i%2 ==0]
print(l2)
# On ne garde que les éléments impairs de la liste l
l3 = [x for x in l if x%2 ==1]
print(l3)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] [0, 4, 16, 36, 64] [1, 9, 25, 49, 81]
Cette syntaxe est aussi valable pour les dictionnaires. Pour les tuples, il suffit de convertir la liste en tuple.
d = {j:j**2 for j in range(5)}
print(d)
t = [j for j in range(5)]
print(tuple(t))
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16} (0, 1, 2, 3, 4)
Lorsqu'une boucle rencontre l'instruction $\mathtt{break}$ elle s'arrête.
for i in range(10):
if i==5:
break
print(i, end=" ")
0 1 2 3 4
i=0
while True:
if i==5:
break
print(i, end=" ")
i=i+1
0 1 2 3 4
Lorsqu'une boucle rencontre l'instruction $\mathtt{continue}$ elle arrête l'itération courante mais n'arrête pas la boucle.
for i in range(10):
if i==5:
continue
print(i, end=" ")
0 1 2 3 4 6 7 8 9
Ainsi, le programme ci-dessous donnerait une boucle infinie
#i=0
#while True:
# if i==5:
# continue
# print(i, end=" ")
# i=i+1
La différence entre les deux étant la présence ou non de l'instruction $\mathtt{return}$. Une fois encore, la définition de la fonction se termine en même temps que l'indentation.
# Pour que ce tutoriel soit validé par l'académie des tutoriels,
# on écrit une procédure qui affiche "Hello World!"
def ceci_est_un_vrai_tutoriel():
print("Hello World!")
# La compilation précédente n'a aucune action car la fonction n'a pas encore été appelée
ceci_est_un_vrai_tutoriel()
# c'est maintenant le cas
Hello World!
# Et maintenant une fonction qui produit le même résultat
def ceci_est_un_vrai_tutoriel():
return "Hello World!"
s = ceci_est_un_vrai_tutoriel()
print(s)
Hello World!
def affiche(a):
print(a)
affiche(1)
affiche("bonjour")
1 bonjour
Le résultat d'une procédure est de type $\mathtt{None}$
type(affiche(1))
1
NoneType
Une fonction peut renvoyer un résultat de n'importe quel type.
def somme(a,b,c):
return a+b+c
somme(a=1,b=2,c=3)
6
Lors de l'appel d'une fonction on peut spécifier le nom de certains arguments. Dans ce cas, l'ordre des paramètres n'a plus d'importance.
def retourne_b_et_pas_juste_le_deuxieme(a,b,c):
return b
print(retourne_b_et_pas_juste_le_deuxieme(b=3,a=2,c=1))
3
Si l'on commence à mixer des arguments implicites (par leur position) et des arguments par leur nom on ne peut pas faire n'importe quoi...
somme(1,c=1,b=3) # Ceci est correct
somme(a=1,1,3) # Ceci n'est pas possible car Python ne sait pas qui est b et qui est c
File "<ipython-input-73-019255840396>", line 3 somme(a=1,1,3) # Ceci n'est pas possible car Python ne sait pas qui est b et qui est c ^ SyntaxError: positional argument follows keyword argument
def forme_un_couple(a=0,b=1):
return a,b
print(forme_un_couple())
print(forme_un_couple(5))
print(forme_un_couple(7,8))
print(forme_un_couple(b=5))
(0, 1) (5, 1) (7, 8) (0, 5)
import math
# ce que contient la bibliothèque math est maintenant disponible.
# Pour voir la liste de qu'elle contient on peut utiliser la commande dir(math)
#dir(math)
# l'affichage étant long, on affiche dans ce tutoriel seulement les 15 derniers éléments
contenu = dir(math)
for i in contenu[-15:-1]:
print(i,",",end=" ")
modf , nan , perm , pi , pow , prod , radians , remainder , sin , sinh , sqrt , tan , tanh , tau ,
Cette bibliothèque contient par exemple la valeur de la constante $\pi$ ou la fonction trigonométrique $\sin$. Pour y accéder, on préfixe par le nom de la bibliothèque.
print(math.pi)
print(math.sin(0))
3.141592653589793 0.0
from math import pi
print(pi)
3.141592653589793
from math import sin, cos
print(sin(0)**2 + cos(0)**2)
1.0
import math as ma
ma.pi
3.141592653589793
from math import sin as sinus
from math import cos as cosinus
print(cosinus(12)**2 + sinus(12)**2)
1.0
Elle a été rapidement vue dans le paragraphe Importer une bibliothèque.
Elle contient les principales constantes ainsi que les fonctions mathématiques usuelles.
import random as rd
for i in range(5):
print(rd.random())
0.3551520938304833 0.14269347885503014 0.7562712583156511 0.5757134159448596 0.3586063839070792
Pour fixer la graine du générateur on utilise la fonction $\mathtt{seed}$. Cela permet d'obtenir toujours le même résultat quand on relance le code.
import random as rd
for i in range(5):
rd.seed(12)
print(rd.random())
0.4745706786885481 0.4745706786885481 0.4745706786885481 0.4745706786885481 0.4745706786885481
Pour la loi uniforme sur l'intervalle $(a,b)$ on utilise la fonction $\mathtt{uniform}$. C'est l'équivalent de $a + (b-a)*\mathtt{random}$.
import random as rd
for i in range(5):
print(rd.uniform(10,12))
11.314945005314511 11.332820942249676 10.285200705850736 10.021720886180136 10.749508984126729
Pour un tirage de nombres entiers entre $a$ et $b$ inclus, on utilise la fonction $\mathtt{randint}$.
import random as rd
for i in range(5):
print(rd.randint(10,15))
12 15 13 15 14
import random as rd
liste = ['a','b','c','d','e']
print("Choix d'un élément :",rd.choice(liste))
print("Choix de 5 éléments dans la liste avec remise :",rd.choices(liste,k=5))
print("Choix de 5 éléments dans la liste sans remise :",rd.sample(liste,5))
Choix d'un élément : b Choix de 5 éléments dans la liste avec remise : ['c', 'd', 'a', 'c', 'a'] Choix de 5 éléments dans la liste sans remise : ['b', 'a', 'c', 'd', 'e']
Le tutoriel de cette bibliothèque est détaillé ici
Le tutoriel de cette bibliothèque est détaillé ici
Le tutoriel de cette bibliothèque est détaillé ici
Le tutoriel de cette bibliothèque est détaillé ici
La bibliothèque $\mathtt{SciPy}$ possède de nombreuses sous-librairies permettant d'attaquer de nombreux problèmes mathématiques numériques :
Une présentation rapide de quelques fonctionnalités est disponible à l'adresse https://www.southampton.ac.uk/~fangohr/teaching/python/book/html/16-scipy.html
Le tutoriel complet est accessible à l'adresse https://docs.scipy.org/doc/scipy/reference/tutorial/index.html
Le logiciel $\mathtt{SageMath}$ écrit en $\mathtt{Python}$ permet de gérer le calcul formel. Un bref tutoriel est disponible à l'adresse http://mmorancey.perso.math.cnrs.fr/TutorielSage.html
Étant écrit en $\mathtt{Python}$ la syntaxe est très proche de celle décrite dans ce tutoriel. S'il est toujours possible d'y importer des modules, la plupart des fonctions utiles pour faire des mathématiques sont déjà présentes dans ce logiciel (mais parfois la syntaxe diffère, voir notamment le paragraphe sur l'algèbre linéaire).