from IPython.core.display import HTML
css_file = './custom.css'
HTML(open(css_file, "r").read())
import sys #only needed to determine Python version number
import matplotlib #only needed to determine Matplotlib version number
print('Python version ' + sys.version)
print('Matplotlib version ' + matplotlib.__version__ )
%reset -f
# Enable inline plotting
%matplotlib inline
%autosave 300
Le corps d'un bloc de code (boucles, sous-routines, etc.) est défini par son indentation: l'indentation est une partie intégrante de la syntaxe de Python.
Le symbole dièse #
indique le début d'un commentaire: tous les caractères entre #
et la fin de la ligne sont ignorés par l'interpréteur.
Dans la plupart des langages informatiques, le nom d'une variable représente une valeur d'un type donné stockée dans un emplacement de mémoire fixe. La valeur peut être modifiée, mais pas le type. Ce n'est pas le cas en Python, où les variables sont typées dynamiquement.
b = 2 # b is an integer
print(b)
b = b*2.0 # b is a float
print(b)
L'affectation b = 2
crée une association entre le nom $b$ et le nombre entier $2$.
La déclaration b*2.0
évalue l'expression et associe le résultat à $b$; l'association d'origine avec l'entier $2$ est détruite.
Maintenant $b$ se réfère à la valeur en virgule flottante $4.0$.
Il faut bien prendre garde au fait que l'instruction d'affectation (=
) n'a pas la même signification que le symbole d'égalité ($=$) en mathématiques (ceci explique pourquoi l'affectation de $3$ à $x$, qu'en Python s'écrit x = 3
, en algorithmique se note souvent $x\leftarrow 3$).
On peut aussi effectuer des affectations parallèles:
a, b = 128, 256
print(a)
print(b)
a,b = b,a
print(a)
print(b)
Attention: Python est sensible à la casse. Ainsi, les noms n
et N
représentent différents objets.
Les noms de variables peuvent être non seulement des lettres, mais aussi des mots; ils peuvent contenir des chiffres (à condition toutefois de ne pas commencer par un chiffre), ainsi que certains caractères spéciaux comme le tiret bas _
(appelé underscore en anglais).
Une chaîne de caractères est une séquence de caractères entre guillemets (simples ou doubles).
Les chaînes de caractères sont concaténées avec l'opérateur plus +
, tandis que l'opérateur :
est utilisé pour extraire une portion de la chaîne.
Voici un exemple:
string1 = 'Press return to exit'
string2 = 'the program'
print(string1 + ' ' + string2) # Concatenation
print(string1[0:12])# Slicing
Une chaîne de caractères est un objet immuable, i.e. ses caractères ne peuvent pas être modifiés par une affectation, et sa longueur est fixe. Si on essaye de modifier un caractère d'une chaîne de caractères, Python renvoie une erreur comme dans l'exemple suivant:
s = 'Press return to exit'
#s[0] = 'p' # Décommenter pour voir l'exception
Une liste est une suite d'objets, rangés dans un certain ordre.
Chaque objet est séparé par une virgule et la suite est encadrée par des crochets.
Une liste n'est pas forcement homogène: elle peut contenir des objets de types différents les uns des autres.
La première manipulation que l'on a besoin d'effectuer sur une liste, c'est d'en extraire et/ou modifier un élément: la syntaxe est ListName[index]
. Voici un exemple:
fraise = [12, 10, 18, 7, 15, 3] # Create a list
print(fraise)
fraise[2]
fraise[1] = 11
print(fraise)
En Python, les éléments d'une liste sont indexés à partir de $0$.
fraise[0], fraise[1], fraise[2], fraise[3], fraise[4], fraise[5]
Si on tente d'extraire un élément avec un index dépassant la taille de la liste, Python renvoi un message d'erreur:
#fraise[6] # Décommenter pour voir l'exception
On peut extraire une sous-liste en déclarant l'indice de début (inclus) et l'indice de fin (exclu), séparés par deux-points: ListName[i:j]
, ou encore une sous-liste en déclarant l'indice de début (inclus), l'indice de fin (exclu) et le pas, séparés par des deux-points: ListName[i:j:k]
.
Cette opération est connue sous le nom de slicing (en anglais).
Un dessin et quelques exemples permettrons de bien comprendre cette opération fort utile:
fraise[2:4]
fraise[2:]
fraise[:2]
fraise[:]
fraise[2:5]
fraise[2:6]
fraise[2:7]
fraise[2:6:2]
fraise[-2:-4]
fraise[-4:-2]
fraise[-1]
À noter que lorsqu'on utilise des tranches, les dépassements d'indices sont licites.
Voici quelques opérations et méthodes très courantes associées aux listes:
a.append(x)
ajoute l'élément x
en fin de la liste a
a.extend(L)
ajoute les éléments de la liste L
en fin de la liste a
, équivaut à a+L
a.insert(i,x)
ajoute l'élément x
en position i
de la liste a
, équivaut à a[i:i]=x
a.remove(x)
supprime la première occurrence de l'élément x
dans la liste a
a.pop([i])
supprime l'élément d'indice i
dans la liste a
et le renvoia.index(x)
renvoie l'indice de la première occurrence de l'élément x
dans la liste a
a.count(x)
renvoie le nombre d'occurrence de l'élément x
dans la liste a
a.sort()
modifie la liste a
en la trianta.reverse()
modifie la liste a
en inversant les élémentslen(a)
renvoie le nombre d'éléments de la liste a
x in a
renvoi True
si la liste a
contient l'élément x
, False
sinonx not
in a renvoi True
si la liste a
ne contient pas l'élément x
, False
sinonmax(a)
renvoi le plus grand élément de la liste a
min(a)
renvoi le plus petit élément de la liste a
a = [2, 37, 20, 83, -79, 21] # Create a list
print(a)
a.append(100) # Append 100 to list
print(a)
L = [17, 34, 21]
a.extend(L)
print(a)
a.count(21)
a.remove(21)
print(a)
a.count(21)
a.pop(4)
print(a)
a.index(100)
a.reverse()
print(a)
a.sort()
print(a)
len(a) # Determine length of list
a.insert(2,7) # Insert 7 in position 2
print(a)
a[0] = 21 # Modify selected element
print(a)
a[2:4] = [-2,-5,-1978] # Modify selected elements
print(a)
ATTENTION: si a
est une liste, la commande b=a
ne crée pas un nouvel objet b
mais simplement une référence (pointeur) vers a
. Ainsi, tout changement effectué sur b
sera répercuté sur a
aussi! Pour créer une copie c
de la liste a
qui soit vraiment indépendante on utilisera la commande deepcopy
du module copy
comme dans les exemples suivants:
import copy
a = [1.0, 2.0, 3.0]
b = a # 'b' is an alias of 'a'
b[0] = 5.0 # Change 'b'
print(a) # The change is reflected in 'a'
print(b)
a = [1.0, 2.0, 3.0]
c = copy.deepcopy(a) # 'c' is an independent copy of 'a'
c[0] = 5.0 # Change 'c'
print(a) # 'a' is not affected by the change
print(c)
Qu'est-ce qui se passe lorsque on copie une liste a
avec la commande b=a
?
En effet, une liste fonctionne comme un carnet d'adresses qui contient les emplacements en mémoire des différents éléments de la liste.
Lorsque on écrit b=a
on dit que b
contient les mêmes adresses que a
(on dit que les deux listes pointent vers le même objet).
Ainsi, lorsqu'on modifie la valeur de l'objet, la modification sera visible depuis les deux alias.
NumPy
)¶Les matrices peuvent être représentées comme des listes imbriquées: chaque ligne est un élément d'une liste. Par exemple, le code
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
définit a
comme la matrice $3\times3$
$$
\begin{pmatrix}
1&2&3\\
4&5&6\\
7&8&9
\end{pmatrix}.
$$
La commande len
(comme length) renvoie la longueur d'une liste.
On obtient donc le nombre de ligne de la matrice avec len(a)
et son nombre de colonnes avec len(a[0])
:
print(a)
print(a[1]) # Print second row (element 1)
print(a[1][2]) # Print third element of second row
print(len(a))
print(len(a[0]))
Dans Python les indices commences à zéro, ainsi a[0]
indique la première ligne, a[1]
la deuxième etc.
$$
\mathbb{A}=
\begin{pmatrix}
a_{00} &a_{01}&a_{02}&\dots\\
a_{10} &a_{11}&a_{12}&\dots\\
\vdots &\vdots&\vdots&\vdots
\end{pmatrix}
$$
Un dictionnaire est une sorte de liste mais au lieu d'utiliser des index, on utilise des clés, c'est à dire des valeurs autres que numériques.
Pour initialiser un dictionnaire, on utile la syntaxe suivante:
a={}
Pour ajouter des valeurs à un dictionnaire il faut indiquer une clé ainsi qu'une valeur:
a["nom"] = "engel"
a["prenom"] = "olivier"
print(a)
La méthode get
permet de récupérer une valeur dans un dictionnaire et, si la clé est introuvable, de donner une valeur à retourner par défaut:
data={}
data = {"name": "Olivier", "age": 30}
print(data.get("name"))
print(data.get("adresse", "Adresse inconnue"))
Pour vérifier la présence d'une clé on utilise in
"nom" in a
"age" in a
Il est possible de supprimer une entrée en indiquant sa clé, comme pour les listes:
del a["nom"]
print(a)
keys
values
items
qui retourne un tuple.fiche = {"nom":"engel","prenom":"olivier"}
for cle in fiche.keys():
print(cle)
for valeur in fiche.values():
print(valeur)
for cle,valeur in fiche.items():
print(cle, valeur)
On peut utiliser des tuples comme clé comme lors de l'utilisation de coordonnées:
b = {}
b[(3,2)]=12
b[(4,5)]=13
b
Comme pour les listes, pour créer une copie indépendante utiliser la méthode copy
:
d = {"k1":"olivier", "k2":"engel"}
e = d.copy()
print(d)
print(e)
d["k1"] = "XXX"
print(d)
print(e)
range
¶La fonction range
crée un itérateur.
Au lieu de créer et garder en mémoire une liste d'entiers, cette fonction génère les entiers au fur et à mesure des besoins:
range(n)
renvoi un itérateur parcourant $0,1,2,\dots,n-1$;range(n,m)
renvoi un itérateur parcourant $n,n+1,n+2,\dots,m-1$;range(n,m,p)
renvoi un itérateur parcourant $n,n+p,n+2p,\dots,m-1$.A = range(0,10)
print(A)
Pour les afficher on crée une list
:
A = list(A)
print(A)
print(list(range(0)))
print(list(range(1)))
print(list(range(3,7)))
print(list(range(0,20,5)))
print(list(range(0,20,-5)))
print(list(range(0,-20,-5)))
print(list(range(20,0,-5)))
print
¶Pour afficher à l'écran des objets on utilise la fonction print(object1, object2, ...)
qui convertis object1, object2
en chaînes de caractères et les affiche sur la même ligne séparés par des espace.
a = 12345,6789
b = [2, 4, 6, 8]
print(a,b)
Le retour à la ligne peut être forcé par le caractère \n
, la tabulation par le caractère \t
.
print("a=", a, "\tb=", b)
print("a=", a, "\nb=", b)
Pour mettre en colonne des nombres on pourra utiliser l'opérateur %
: la commande print('%format1, %format2,...' %(n1,n2,...)
affiche les nombres n1,n2,...
selon les règles %format1, %format2,...
. Typiquement on utilise
wd
pour un entierw.df
pour un nombre en notation floating pointw.de
pour un nombre en notation scientifiqueoù w
est la largeur du champ total et d
le nombre de chiffres après la virgule.
a = 1234.56789
n = 9876
print('%7.2f' %a)
print('n = %6d' %n)
print('n = %06d' %n)
print('%12.3f %6d' %(a,n))
print('%12.4e %6d' %(a,n))
+
Addition -
Soustraction *
Multiplication/
Division**
Exponentiation//
Quotient de la division euclidienne%
Reste de la division euclidiennea = 100
b = 17
c = a-b
a,b,c
a = 2
c = b+a
a,b,c
a = 3
b = 4
c = a
a = b
b = c
a, b, c
Certains de ces opérations sont aussi définies pour les chaînes de caractères et les listes comme dans l'exemple suivant:
s = 'Hello '
t = 'to you'
a = [1, 2, 3]
print(3*s) # Repetition
print(3*a) # Repetition
print(a + [4, 5]) # Append elements
print(s + t) # Concatenation
#print(3 + s) # Décommenter pour voir l'exception
Il existe aussi les opérateurs augmentés:
On écrit | Équivaut à |
---|---|
a += b |
a = a + b |
a -= b |
a = a - b |
a *= b |
a = a * b |
a /= b |
a = a / b |
a **= b |
a = a ** b |
a %= b |
a = a % b |
Les opérateurs de comparaison renvoient True
si la condition est vérifiée, False
sinon.
Ces opérateurs sont
On écrit | Ça signifie |
---|---|
< |
$<$ |
> |
$>$ |
<= |
$\le$ |
>= |
$\ge$ |
== |
$=$ |
!= |
$\neq$ |
in |
$\in$ |
Attention: bien distinguer l'instruction d'affectation =
du symbole de comparaison ==
.
Pour combiner des conditions complexes (par exemple $x>-2$ et $x^2<5$), on peut combiner des variables booléennes en utilisant les connecteurs logiques:
On écrit | Ça signifie |
---|---|
and |
et |
or |
ou |
not |
non |
Deux nombres de type différents (entier, à virgule flottante, etc.) sont convertis en un type commun avant de faire la comparaison. Dans tous les autres cas, deux objets de type différents sont considérés non égaux.
a = 2 # Integer
b = 1.99 # Floating
c = '2' # String
print('a>b?',a>b)
print('a==c?',a==c)
print('(a>b) and (a==c)?',(a>b) and (a==c))
print('(a>b) or (a==c)?',(a>b) or (a==c))
Supposons de vouloir calculer les images de certains nombres par une fonction polynomiale donnée. Si la fonction en question est un peu longue à saisir, par exemple $f\colon x\mapsto 2x^7-x^6+5x^5-x^4+9x^3+7x^2+8x-1$, il est rapidement fastidieux de la saisir à chaque fois que l'on souhaite calculer l'image d'un nombre par cette fonction.
def
¶Il est tout à fait possible de définir une fonction (au sens du langage Python) qui ressemble à une fonction mathématique. La syntaxe est la suivante:
def FunctionName(parameters):
statements
return values
La déclaration d'une nouvelle fonction commence par le mot-clé def
.
Ensuite, toujours sur la même ligne, vient le nom de la fonction (ici FunctionName
) suivi des paramètres formels de la fonction (ici parameters
), placés entre parenthèses, le tout terminé par deux-points (on peut mettre autant de paramètres formels qu'on le souhaite et éventuellement aucun).
Une fois la première ligne saisie, on appuie sur la touche Entrée
: le curseur passe à la ligne suivante avec une indentation.
Si l'instruction return
est absente, la fonction renvoi l'objet None
.
def f(x):
return 2*x**7 - x**6 + 5*x**5 - x**4 + 9*x**3 + 7*x**2 + 8*x -1
f(2)
Attention: dès que Python atteint l'instruction return something
, il renvoi l'objet something
et abandonne aussitôt après l'exécution de la fonction (on parle de code mort pour désigner les lignes qui suivent l'instruction return
.
Voici un bêtisier pour mieux comprendre les règles:
#def f(x) # Décommenter pour voir l'exception
# Décommenter pour voir l'exception
#def f(x):
#return 2*x**7-x**6+5*x**5-x**4+9*x**3+7*x**2+8*x-1
return
et donc tout appel de la fonction aura comme réponse None
, # Décommenter pour voir l'exception
#def f(x):
# 2*x**7-x**6+5*x**5-x**4+9*x**3+7*x**2+8*x-1
#print(f(2))
print 'Hello'
n'est jamais lue par Python car elle apparait après l'instruction return
.def f(x):
a = 2*x**7-x**6+5*x**5-x**4+9*x**3+7*x**2+8*x-1
return a
print('Hello')
print(f(2))
Attention: les variables définies à l'intérieur d'une fonction ne sont pas visibles depuis l'extérieur de la fonction. On exprime cela en disant qu'une telle variable est locale à la fonction. De plus, si une variable existe déjà avant l'exécution de la fonction, tout se passe comme si, durant l'exécution de la fonction, cette variable était masquée momentanément, puis restituée à la fin de l'exécution de la fonction.
Dans l'exemple suivant, la variable x
est une variable locale à la fonction f
: crée au cours de l'exécution de la fonction f
, elle est supprimée une fois l'exécution terminée:
# Décommenter pour voir l'exception
def f(y):
x = 2
return 4.*y
print(f(5))
#print(x)
Dans l'exemple suivant, la variable x
est une variable qui vaut $6$ à l'extérieur de la fonction et $7$ au cours de l'exécution de la fonction f
:
x = 6.
def f(y):
x = 7
return x*y
print(x)
print(f(1.))
print(x)
Dans l'exemple suivant la fonction derivatives
approche les dérivées première et seconde d'une fonction $f$ par les formules
\begin{align*}
f'(x)&\simeq\frac{f(x+h)-f(x-h)}{2h},
&
f''(x)&\simeq\frac{f(x+h)-2f(x)+f(x-h)}{h^2}
\end{align*}
import math
def derivatives(f,x,h):
df = (f(x+h)-f(x-h))/(2.*h)
ddf = (f(x+h)-2.*f(x)+f(x-h))/h**2
return df,ddf
Si on veut calculer la valeur des dérivées première et seconde de la fonction $x\mapsto\cos(x)$ en $x=\frac{\pi}{2}$ il suffit d'écrire
df, ddf = derivatives(math.cos,math.pi/2,1.0e-5)
print('First derivative =', df)
print('Second derivative =', ddf)
Attention: si une liste est passée comme paramètre d'une fonction et cette fonction la modifie, cette modification se répercute sur la liste initiale. Si ce n'est pas le résultat voulu, il faut travailler sur une copie de la liste.
def squares(a):
for i in range(len(a)):
a[i] = a[i]**2
a = [1,2,3,4]
print(a)
squares(a)
print(a)
Quand on définit la fonction $f\colon x\mapsto 2x$ avec
def f(x):
return 2*x
on fait deux choses: on crée l'objet «fonction qui a $x$ associe $2x$» et on affecte cet objet à une variable (globale) $f$:
f(3)
On peut aussi créer une fonction sans lui donner de nom, c'est une fonction lambda: la ligne
(lambda x: 2*x)(3)
se lit «fonction qui a $x$ associe $2x$» (i.e. $x\mapsto 2x$) évaluée en $x=3$.
La ligne
g = lambda x: x*2
g(3)
équivaut à
def g(x):
return x*2
g(3)
Les fonctions lambda
sont surtout utiles pour passer une fonction en paramètre à une autre (par exemple, pour appliquer la fonction à tous les éléments d'une liste):
m = map(lambda x: x+1, [1, 3, 42])
list(m)
Une fonction lambda peut avoir plusieurs paramètres:
somme = lambda x,y : x + y
somme(10, 3)
Pour éviter la tentation de code illisible, Python limite les fonctions lambda: une seule ligne et return
implicite.
Si on veut écrire des choses plus compliquées, on utilise def
(on peut toujours).
Même avec ces limitations, on peut souvent s'en sortir.
Par exemple
def abs_avec_def(x):
if x >= 0:
return x
else:
return -x
list(map(abs_avec_def, [-1, 0, 42]))
est équivalent à
list(map(lambda x: x if x >= 0 else -x, [-1, 0, 42]))
Cependant, dans des nombreuses situations il sera plus simple d'utiliser les list-comprehensions.
Les listes définies par compréhension permettent de générer des listes de manière très concise sans avoir à utiliser des boucles. La syntaxe pour définir une liste par compréhension est très proche de celle utilisée en mathématiques pour définir un ensemble:
[f(x) for x in E]
liste = [2, 4, 6, 8, 10]
[3*x for x in liste]
[[x,x**3] for x in liste]
[3*x for x in liste if x>5]
[3*x for x in liste if x**2<50]
liste2 = range(3)
[x*y for x in liste for y in liste2]
Le code vu à propos des lambda functions
m = map(lambda x: x+1, [1, 3, 42])
list(m)
équivaut à
[x+1 for x in [1, 3, 42]]
Pour un entier $n\in\mathbb{N}$ donné, on calcule la liste de ses diviseurs :
n = 100
[d for d in range(1,n+1) if (n%d==0)]
Après avoir définie une liste, on affiche d'abord les carrés des éléments de la liste liste donnée, ensuite les nombres paires, enfin les carrés pairs:
liste = [1, 2, 3, 4, 5, 6, 7]
print([x**2 for x in liste])
print([x for x in liste if x % 2 == 0])
print([x**2 for x in liste if x**2 % 2 == 0])
print([x for x in [a** 2 for a in liste] if x % 2 == 0])
Supposons vouloir définir la fonction valeur absolue:
$$
\lvert x\rvert =\begin{cases}x&\text{si }x\ge0,\\-x&\text{sinon.}\end{cases}
$$
On a besoin d'une instruction qui opère une disjonction de cas.
En Python il s'agit de l'instruction de choix introduite par le mot-clé if
.
La syntaxe est la suivante:
if condition_1:
instruction_1.1
instruction_1.2
elif condition_2:
instruction_2.1
instruction_2.2
...
else:
instruction_n.1
instruction_n.2
où condition_1
, condition_2
... représentent des ensembles d'instructions dont la valeur est True
ou False
(on les obtient en général en utilisant les opérateurs de comparaison). La première condition condition_i
ayant la valeur True
entraîne l'exécution des instructions instruction_i.1
et instruction_i.2
.
Si toutes les conditions sont fausses, les instructions instruction_n.1
et instruction_n.2
sont exécutées.
Bien noter le rôle essentiel de l'indentation qui permet de délimiter chaque bloc d'instructions et la présence des deux points après la condition du choix (mot clé if
) et après le mot clé else
.
Voici un exemple pour établir si un nombre est positif:
def sign_of(a):
if a < 0.0:
sign = 'negative'
elif a > 0.0:
sign = 'positive'
else:
sign = 'zero'
return sign
a = 2.0
print ('a is ' + sign_of(a))
a = -2.0
print ('a is ' + sign_of(a))
a = 0.0
print ('a is ' + sign_of(a))
La fonction valeur absolue peut être définie comme suit:
def val_abs(x):
if x>0:
return x
else:
return -x
print(val_abs(5))
print(val_abs(-5))
Les structure de répétition se classent en deux catégories: les répétitions conditionnelles pour lesquelles le bloc d'instructions est à répéter autant de fois qu'une condition est vérifiée, et les répétitions inconditionnelles pour lesquelles le bloc d'instructions est à répéter un nombre donné de fois.
while
: répétition conditionnelle¶Le constructeur while
a la forme générale suivante (attention à l'indentation et aux deux points):
while condition:
instruction_1
instruction_2
où condition
représente des ensembles d'instructions dont la valeur est True
ou False
.
Tant que la condition condition
a la valeur True
, on exécute les instructions instruction_i
.
Attention: si la condition ne devient jamais fausse, le bloc d'instructions est répété indéfiniment et le programme ne se termine pas.
Voici un exemple pour créer la liste $\left[1,\frac{1}{2},\frac{1}{3},\frac{1}{4}\right]$:
nMax = 5
n = 1
a = [] # Create empty list
while n<nMax:
a.append(1.0/n) # Append element to list
n += 1
print(a)
Dans l'exemple suivant on calcul la somme des $n$ premiers entiers:
def somme(n):
s ,i = 0, 0
while i<n:
i += 1
s += i
return s
n=100
print(somme(n))
print('En effet n(n+1)/2=',n*(n+1)/2)
for
¶Lorsque l'on souhaite répéter un bloc d'instructions un nombre déterminé de fois, on peut utiliser un compteur actif, c'est-à-dire une variable qui compte le nombre de répétitions et conditionne la sortie de la boucle. C'est la structure introduite par le mot-clé for
qui a la forme générale suivante (attention à l'indentation et aux deux points):
for target in sequence:
instruction_1
instruction_2
où target
est le compteur actif et sequence
est un itérateur (souvent généré par la fonction range
ou une liste ou une chaîne de caractères).
Tant que target
appartient à sequence
, on exécute les instructions instruction_i
.
Voici un exemple pour créer la liste $\left[1,\frac{1}{2},\frac{1}{3},\frac{1}{4}\right]$ avec un itérateur généré par la fonction range
:
nMax = 5
a = [] # Create empty list
for n in range(1,nMax):
a.append(1/n) # Append element to list
print(a)
La même avec avec une list-comprhension:
a=[1/n for n in range(1,nMax)]
print(a)
break
et continue
¶L'instruction break
sort de la plus petite boucle for
ou while
englobante.
for i in [1,2,3,4,5]:
if i==4:
print("J'ai trouvé")
break
print(i)
for lettre in 'Notebook IPython':
if lettre=='P':
break
print(lettre)
L'instruction continue
continue sur la prochaine itération de la boucle.
a=0
while a<=5:
a+=1
if a%2==0:
continue
print(a)
print("Boucle terminée")
Les instructions de boucle ont une clause else
qui est exécutée lorsque la boucle se termine par épuisement de la liste (avec for
) ou quand la condition devient fausse (avec while
), mais pas quand la boucle est interrompue par une instruction break
.
La boucle suivante recherche des nombres premiers:
for n in range(2,10):
for x in range(2,n):
if n%x==0:
print(n, 'egale', x, '*', n/x)
break # on sort de la boucle 'for' interne
else:
print(n, 'est un nombre premier')
Un module est une collection de fonctions.
Il y a différents types de modules: ceux qui sont inclus dans la version de Python comme random
ou math
, ceux que l'on peut rajouter comme numpy
ou matplotlib
et ceux que l'on peut faire soi-même (il s'agit dans les cas simples d'un fichier Python contenant un ensemble de fonctions).
Pour importer un module, on peut utiliser la commande import ModuleName
.
Il est alors possible d'obtenir une aide sur le module avec la commande help(ModuleName)
.
La liste des fonctions définies dans un module peut être affichée par la commande dir(ModuleName)
.
Les fonctions s'utilisent sous la forme ModuleName.FunctionName(parameters)
.
Il est également possible d'importer le contenu du module sous la forme from ModuleName import *
et alors les fonctions peuvent être utilisées directement par FunctionName(parameters)
.
Python offre par défaut une bibliothèque de plus de deux cents modules qui évite d'avoir à réinventer la roue dès que l'on souhaite écrire un programme. Ces modules couvrent des domaines très divers: mathématiques (fonctions mathématiques usuelles, calculs sur les réels, sur les complexes, combinatoire\dots), administration système, programmation réseau, manipulation de fichiers, etc. Ici on en présente seulement quelques-uns, à savoir ce dont on se servira dans les projets.
math
¶Dans Python seulement quelque fonction mathématique est prédéfinie:
abs(a)
Valeur absolue de $a$max(suite)
Plus grande valeur de la suitemin(suite)
Plus petite valeur de la suite round(a,n)
Arrondi $a$ à $n$ décimales prèspow(a,n)
Exponentiation, renvoi $a^n$sum(L)
Somme des éléments de la suitedivmod(a,b)
Renvoie quotient et reste de la division de $a$ par $b$cmp(a,b)
Renvoie $\begin{cases}-1&\text{si }a<b,\\0&\text{si }a=b,\\1&\text{si }a>b.\end{cases}$math
.
Comme mentionné précédemment, on dispose de plusieurs syntaxes pour importer un module:import math
print(math.pi)
print(math.sin(math.pi))
print(math.log(1.0))
from math import *
print(pi)
print(sin(pi))
print(log(1.0))
Voici la liste des fonctions définies dans le module math
:
import math
dir(math)
Notons que le module définit les deux constantes $\pi$ (pi
) et $e$ (e
).
random
¶Ce module propose diverses fonctions permettant de générer des nombres (pseudo-)aléatoires qui suivent différentes distributions mathématiques. Il apparait assez difficile d'écrire un algorithme qui soit réellement non-déterministe (c'est-à-dire qui produise un résultat totalement imprévisible). Il existe cependant des techniques mathématiques permettant de simuler plus ou moins bien l'effet du hasard. Voici quelques fonctions fournies par ce module:
random.randrange(p,n,h)
choisit un éléments aléatoirement dans la liste range(p,n,h)
random.randint(a,b)
choisit un entier aléatoirement dans l'intervalle $[a;b]$random.choice(seq)
choisit un éléments aléatoirement dans la liste seq
random.random()
renvoie un décimal aléatoire dans $[0;1[$random.uniform(a,b)
choisit un décimal aléatoire dans $[a;b]$import random
random.randrange(50,100,5)
random.randint(50,100)
random.choice([1,7,10,11,12,25])
random.random()
random.uniform(10,20)
matplotlib
¶Le tracé de courbes scientifiques peut se faire à l'aide du module matplotlib
.
Matplotlib
est un package complet; pylab
et pyplot
sont des modules de matplotlib
qui sont installés avec matplotlib
.
Pylab
associe les fonctions de pyplot
(pour les tracés) avec les fonctionnalité du module numpy
pour obtenir un environnement très proche de celui de MATLAB.
On peut écrire et exécuter des script Python (qui utilisent Matplotlib) en ligne à l'adresse https://trinket.io/python/a8645625fd
Pour l'utiliser, on peut importer le module pylab
.
La référence complète de matplotlib est lisible à l'adresse: http://matplotlib.sourceforge.net/matplotlib.pylab.html Il est en particulier recommandé de regarder les screenshots (captures d'écrans), qui sont donnés avec le code utilisé pour les générer.
Vous pouvez consulter aussi
Pour tracer le graphe d'une fonction $f\colon[a,b]\to\mathbb{R}$, Python a besoin d'une grille de points $x_i$ où évaluer la fonction, ensuite il relie entre eux les points $(x_i,f(x_i))$ par des segments. Plus les points sont nombreux, plus le graphe est proche du graphe de la fonction $f$. Pour générer les points $x_i$ on peut utiliser
linspace(a,b,n+1)
qui construit la liste de $n+1$ éléments
$$
\left[a,a+h,a+2h,\dots,b=a+nh\right]
\quad\text{avec } h=\frac{b-a}{n}
$$arange(a,b,h)
qui construit la liste de $n=E(\frac{b-a}{h})+1$ éléments
$$
\left[a,a+h,a+2h,\dots,a+nh\right]
$$
Voici un exemple avec une sinusoïde:%matplotlib inline
from matplotlib.pylab import *
x = linspace(-5,5,101) # x = [-5,-4.9,-4.8,...,5] with 101 elements
y = sin(x) # operation is broadcasted to all elements of the array
plot(x,y);
#show()
ou encore
from matplotlib.pylab import *
x = arange(-5,5,0.1) # x = [-5,-4.9,-4.8,...,5] with 101 elements
y = sin(x) # operation is broadcasted to all elements of the array
plot(x,y);
# show()
On obtient une courbe sur laquelle on peut zoomer, modifier les marge et sauvegarder dans différents formats.
On peut même tracer plusieurs courbes sur la même figure. Par exemple, dans la figure suivante, on a tracé la même fonction: la courbe bleu correspond à la grille la plus grossière, la courbe rouge correspond à la grille la plus fine:
from matplotlib.pylab import *
a = linspace(-5,5,5)
fa = sin(a) # matplotlib importe numpy qui redefinie les fonctions de base pour pouvoir les appliquer a un vecteur
plot(a,fa,'b-',label="$f(a)$");
b = linspace(-5,5,101)
fb = sin(b)
plot(b,fb,'r-.',label="$f(b)$" );
legend();
Pour tracer plusieurs courbes sur le même repère, on peut les mettre les unes à la suite des autres en spécifiant la couleur et le type de trait, changer les étiquettes des axes, donner un titre, ajouter une grille, une légende etc.
Par exemple, dans le code ci-dessous "r-"
indique que la première courbe est à tracer en rouge (red) avec un trait continu, et "g."
que la deuxième est à tracer en vert (green) avec des points.
from matplotlib.pylab import *
x = linspace(-5,5,101)
y1 = sin(x)
y2 = cos(x)
plot(x,y1,"r-",x,y2,"g.")
legend(['sinus','cosinus'])
xlabel('abscisses')
ylabel('ordonnees')
title('Comparaison de sin(x) et cos(x)')
grid(True)
Quelques options de pylab
:
Line style | Color | Symbols | |||
---|---|---|---|---|---|
- |
solid line | b |
blue | v |
triangle down symbols |
-- |
dashed line | r |
red | > |
triangle right symbols |
: |
dotted line | m |
magenta | + |
plus symbols |
-. |
dash-dot line | k |
black | D |
diamond symbols |
. |
points | g |
green | , |
pixels |
o |
filled circles | c |
cyan | < |
triangle left symbols |
^ |
filled triangles up | y |
yellow | s |
square symbols |
w |
white | x |
cross symbols | ||
* |
star symbols |
On peut déplacer la légende en spécifiant l'une des valeurs suivantes:
best
, upper right
, upper left
, lower right
, lower left
, center right
, center left
, lower center
, upper center
, center
:
from matplotlib.pylab import *
x = arange(-pi,pi,0.05*pi)
plot(x,sin(x),'co',x,cos(x),'mD')
legend(['sinus','cosinus'],loc='upper left')
axis([-pi, pi, -1, 1]) # axis([xmin, xmax, ymin, ymax])
from matplotlib.pylab import *
a = linspace(-5,5,5)
fa = sin(a)
plot(a,fa,ls='--', lw=3, color="blue", label=r"$f(a)$")
b = linspace(-5,5,10)
fb = sin(b)
plot(b,fb,ls='--', lw=2.0, color="orange", label=r"$f(b)$")
c = linspace(-5,5,101)
fc = sin(c)
plot(c,fc,ls='-.', lw=0.5, color="green", label=r"$f(c)$")
plot([0], [0.5], lw=0.5, marker='o', color="cyan")
text(0, 0.6,r"$\sigma_i$", horizontalalignment='center', fontsize=20)
xlim(-5, 5)
ylim(-1, 1)
yticks([-1, -0.5, 0, 1])
xticks([-4, -2, 0, 2])
xlabel("$x$", fontsize=18)
ylabel("$y$", fontsize=18)
legend(bbox_to_anchor=(1.04,1),loc='upper left', ncol=1, fontsize=14, frameon=False);
On génère deux fenêtres contenant chacune un graphe:
from matplotlib.pylab import *
x = arange(-pi,pi,0.05*pi)
figure(1)
plot(x, sin(x), 'r')
figure(2)
plot(x, cos(x), 'g')
La fonction subplot(x,y,z)
subdivise la figure sous forme d'une matrice (x,y)
et chaque case est numérotée, z
étant le numéro de la case où afficher le graphe. La numérotation se fait de gauche à droite, puis de haut en bas, en commençant par $1$.
from matplotlib.pylab import *
x = arange(-pi,pi,0.05*pi)
figure(figsize=(10, 10), facecolor="#f1f1f1")
# axes coordinates as fractions of the canvas width and height
#left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
#axes((left, bottom, width, height), facecolor="#e1e1e1")
subplot(4,3,1)
plot(x, sin(x), 'r')
subplot(4,3,5)
plot(x, cos(x), 'g')
subplot(4,3,9)
plot(x, x*x, 'b')
subplot(4,3,12)
plot(x, exp(-x*x), 'm')
Pour afficher une animation on utilisera le module animation
de matplotlib
. Voici un exemple avec deux méthodes différentes : la première utilise la commande magique %matplotlib inline
, la deuxième la commande magique %matplotlib notebook
qui permet d'intéragir avec l'animation.
%reset -f
%matplotlib inline
from matplotlib.pylab import *
import matplotlib.animation as animation
from IPython.display import display, clear_output
fig = figure()
axis([0,3,-1,1])
line, = plot([],[],lw=2)
x = linspace(0,3,100)
animate = lambda i: line.set_data(x, cos(2*pi*(x-0.01*i)))
# CI
plot(x,cos(2*pi*x))
# Marche en temps
for i in range(len(x)):
animate(i)
clear_output(wait=True)
display(fig)
clear_output(wait=True)
%reset -f
%matplotlib notebook
%matplotlib notebook
from matplotlib.pylab import *
from matplotlib import animation
x = linspace(0,3,100)
# First set up the figure, the axis, and the plot element we want to animate
fig = figure() # initialise la figure
line, = plot([],[],lw=2)
axis([0,3,-1,1])
# Define the initialization function, which plots the background of each frame:
# init = lambda : plot([],[])
init = lambda : plot(x,cos(2*pi*x))
# Define the animation function, which is called for each new frame:
animate = lambda i: line.set_data(x,cos(2*pi*(x-0.01*i)))
# call the animator. blit=True means only re-draw the parts that have changed.
ani = animation.FuncAnimation(fig, animate, init_func=init, frames=100, blit=False, interval=20, repeat=False)
# Eventually
# from IPython.display import HTML, Image
# ani.save('animation.gif', writer='imagemagick', fps=60)
# Image(url='animation.gif')
La représentation graphique de l’évolution d’une fonction $f$ de deux variables $x$ et $y$ n'est pas une tâche facile, surtout si le graphique en question est destiné à être imprimé. Dans ce type de cas, un graphe faisant apparaître les lignes de niveaux de la fonction en question peut être une solution intéressante et lisible. Commençons donc par considérer l'exemple simple d'une fonction de la forme: $$ f(x,y)= \frac{\sin(x^2+y^2)}{x^2+y^2} $$
Le tracé de cette fonction en courbes de niveaux va nécessiter la création d’un maillage bidimensionnel permettant de stocker l’intervalle de chacune des variables.
La fonction destinée à cela s’appelle meshgrid
(incluse dans le module NumPy
).
On construit donc le maillage en question sur le rectangle $[-5;5]\times[-5;5]$.
La fonction meshgrid
fait appel dans ce cas à deux fonctions linspace
pour chacune des variables.
z
est ici un objet array
qui contient les valeurs de la fonction $f$ sur chaque nœud du maillage.
%matplotlib inline
from matplotlib.pylab import *
x=linspace(-2*pi,2*pi,200)
y=linspace(-2*pi,2*pi,200)
xx,yy = meshgrid(x,y)
z = sin(xx**2 + yy**2) / (xx**2 + yy**2)
imshow(z);
Pour tracer l’évolution de $f$ en lignes de niveaux on utilisera les fonctionscontour
et contourf
avec comme arguments les variables x
et y
, les valeurs de z
correspondantes (et eventuellement le nombre de lignes de niveaux choisit).
h = contour(x,y,z)
h = contour(x,y,z,20)
h = contourf(x,y,z,20)
Par défaut, ces courbes de niveaux sont colorées en fonction de leur altitude $z$ correspondante.
S’il n’est pas possible d’utiliser de la couleur, on peut imposer une couleur uniforme pour le graphe et utiliser des labels sur les lignes de niveaux afin de repérer leurs altitudes.
La fonction en question s’appelle clabel
et prend comme principal argument la variable graphe précédente.
La première option inline=1
impose d’écrire les valeurs sur les lignes de niveaux, les deux options suivantes gérant la taille de la police utilisée et le format d’écriture des valeurs.
x=linspace(-2,2,101)
y=linspace(-2,2,101)
xx,yy = meshgrid(x,y)
z = xx**2 + yy**2
graphe4 = contour(x,y,z,8,colors='grey')
clabel(graphe4,inline=1,fontsize=10,fmt='%1.4f')
Pour visualiser un champ de vecteur on pourra utiliser streamplot
:
x=linspace(-2,2,101)
y=linspace(-2,2,101)
xx,yy = meshgrid(x,y)
z = xx**2 + yy**2
dx = 2*xx
dy = 2*yy
speed = sqrt(dx*dx+dy*dy)
streamplot(xx, yy, dx, dy, density=1.2, color=speed, linewidth=2*speed / speed.max())