Ce notebook est proposé dans le cadre d'une préparation au ** Cours de mathématiques & informatique ** en B.C.P.S.T.2 - Externat des enfants nantais proposé par J. Laurentin. On pourra, si on le souhaite, trouver des compléments notamment sur le programme officiel en visitant le site de la classe mathsinfo-bcpst2-eden.fr
Le Notebook d'IPython est un environnement intéractif pour écrire et faire tourner du code Python.
Des cellules de code, précédées d'un In []
permettent de rentrer des lignes de codes comme vous avez pu le faire jusqu'à présent dans la fenêtre de commande de Pyzo.
A titre d'exemple, placez votre curseur sur la ligne ci-dessous et appuyez sur la touche <enter>
. Vérifiez que l'instruction n'a pas été exécutée mais en revanche un saut de ligne a été inséré...
Pour exécuter le code Python d'une cellule, il vous faut, au choix, taper <maj-enter>
ou cliquer sur le bouton [lecture] de la barre des tâches ci-dessus (ou encore utiliser le menu Cell>Run and Select Below...
).
Il suffit d'essayer :
a,b = 1,5
print('a*b vaut',a*b)
a*b vaut 5
Il est toujours possible d'effacer une cellule grâce aux ciseaux du bandeau situé en haut de page et en créer une nouvelle grâce au symbole '+'.
Mais c'est le plus souvent inutile car il est possible de relancer une ligne autant de fois qu'on le souhaite après l'avoir modifiée.
Par exemple, modifiez la ligne de code In [1]
pour initialiser la variable b
à 5 et afficher la valeur de a+b
.
vous devriez voir afficher 'a+b vaut 6'.
D'un point de vue pratique, on notera que toutes les fonctionnalités d'Ipython sont ici opérationnelles.
On peut par exemple retrouver le chemin du dossier dans lequel on travaille :
pwd
'C:\\Users\\Jérôme\\Documents\\BCPST2\\Jupyter'
On peut aussi importer les bibliothèques de son choix.
Par exemple :
from math import *
import numpy as np
On peut désormais faire :
x = 2
y = exp(x)-1
print(x,'|',y)
2 | 6.38905609893065
X = np.linspace(0,1,10)
print(X)
[ 0. 0.11111111 0.22222222 0.33333333 0.44444444 0.55555556 0.66666667 0.77777778 0.88888889 1. ]
Il est aussi possible d'écrire des fonctions plus complexes.
Par exemple pour la suite de Fibonacci définie par $u_0=1=u_1$ et $u_{n+2}=u_{n+1}+u_n$, $\forall n\geq 0$
on calculera et on affichera ses dix premiers termes en écrivant :
a,b=1,1 # initialisation de deux premiers termes
print(a,b,end = " ")
n=1
while n<11 :
a,b = b,a+b
print(b,end = " ")
n = n+1
1 1 2 3 5 8 13 21 34 55 89 144
** Attention ** Vous noterez que tous les termes de la suite ont été affichés sur une seule ligne.
Ce résultat est obtenu grâce à l'argument end = " "
fourni à la fonction print()
.
Supprimez cet argument et vérifiez que les termes sont affichés les uns en dessous des autres.
Avec Python, tout est objet : données, fonctions, modules...
Un objet :
(par exemple : int, float, str);
Un objet est référencé par un identificateur :
a = 5 # a est l'identificateur et 5 est une expression évaluée comme objet.
# il est possible d'afficher l'identité et le type de l'objet référencé :
print(id(a)) # identité
print(type(a)) # type
1409942128 <class 'int'>
b = a # deuxième nom (étiquette ou référence) pour l'entier 5
print(id(b))
print(type(b))
1409942128 <class 'int'>
c = 5.0 # nouvel identificateur qui pointe cette fois vers 5.0
type(c)
float
print(id(a),id(b),id(c))
1409942128 1409942128 4395697064
a == b # égalité des valeurs des deux objets
True
a == c # égalité des valeurs
True
a is c # test l'égalité des identités
False
a is b # test l'égalité des identités
True
On retiendra que a, b et c ont même valeur mais que c se distingue de a et b car son identité et son type son distincts.
** Attention ! ** Tous les objets ne sont pas modifiables !
Un objet dont le contenu peut être changé est dit ** mutable ** (non mutable dans le cas contraire).
A titre d'exemple une chaîne de caractère est un objet non mutable tandis qu'une liste est un objet mutable.
T = 'Feci est un texte non modifiable'
print(T)
Feci est un texte non modifiable
T[0]='C'
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-20-9794c11e21e5> in <module>() ----> 1 T[0]='C' TypeError: 'str' object does not support item assignment
L = [12,-5.0,'oups'];L
[12, -5.0, 'oups']
L[2]=3;L
[12, -5.0, 3]
print(L)
[12, -5.0, 3]
** Remarque importante ** sur les copies d'objets qui peuvent donner lieu à des erreurs difficiles à déceler :
M = L
print(M)
[12, -5.0, 3]
M[1]=60 # modification de la liste M
print(M)
[12, 60, 3]
La question est de savoir si la liste L
aussi a été modifiée...
L
[12, 60, 3]
L is M # L et M ont la même identité. Ils pointent vers le même objet et il est normal que L soit modifiée également.
True
Il existe deux solutions pour faire la copie d'un objet : La copie * superficielle * ou la copie * profonde .
Nous verrons ça à la fin du paragraphe 3.2 Modification d'une liste *
Les listes représentent un type de données composées extrêment utiles sous Python.
On peut les voir comme une collection d'éléments séparés par des virgules, l'ensemble étant enfermé dans des crochets.
Les éléments peuvent être de type très différents. Par exemple :
L1 = [1,2,3.5,'7',-2.4,'test']
print(L1)
[1, 2, 3.5, '7', -2.4, 'test']
Il est possible d'accéder à n'importe quel élément d'une liste en indiquant entre crochets l'index numérique qui correspond à la position de l'élément.
Essayez successivement dans la ligne ci-dessous : L1[2]
, L1[0]
, L1[5]
, L1[-1]
, L1[-1][1]
# Obtenir un élément de la liste :
L1[2]
3.5
On obtient la longueur d'une liste ou d'une chaîne en faisant appel à la fonction len()
:
n1 = len(L1)
print('la longueur de L1 vaut : ',n1)
print('la longueur de la chaîne de caractère "test" vaut : ',len(L1[-1]))
la longueur de L1 vaut : 6 la longueur de la chaîne de caractère "test" vaut : 4
Il est aussi possible de savoir si un élément est dans une liste :
3 in L1
False
u = 3.5
if u in L1:
print(u,' est dans L1')
3.5 est dans L1
L1[0]
et L1[1]
sont des entiers).L1[2]
est un "nombre réel" ou "nombre à virgule flottante).L1[3]
et L1[5]
sont des chaînes de caractères).On obiendra le type d'un élement en faisant appel à la fonction type()
.
Par exemple on essaira ci-dessous type(L1)
, type(L1[0])
, type(L1[2])
ou encore type(L1[3])
:
type(L1)
list
Remarque : Dans le cas de L1[3]
on vérifiera qu'il s'agit bien d'un caractère et non d'un entier !
Cela étant, il est possible d'accéder à bien mieux qu'à un seul élément d'une liste.
Il est en effet possible d'extraire n'importe quelle sous-liste et ce dans l'ordre de votre choix.
Commençons par extraire les trois premiers éléments de L1
:
print(L1[0:3])
print(L1[:3])
[1, 2, 3.5] [1, 2, 3.5]
print('L1 vaut : ',L1)
print(L1[1:])
print(L1[1:-1])
print(L1[1:4:2]) # index de 1 à 4 (exclus) par pas de 2.
print(L1[4:1:-1]) # index de 4 à 1 (exclus) par pas de -1.
print(L1[::-1]) # Affichage inversé de tout L1.
L1 vaut : [1, 2, 3.5, '7', -2.4, 'test'] [2, 3.5, '7', -2.4, 'test'] [2, 3.5, '7', -2.4] [2, '7'] [-2.4, '7', 3.5] ['test', -2.4, '7', 3.5, 2, 1]
A vous de jouer en créant à la suite de ce texte une nouvelle ligne de code (cliquer sur le symbole '+' dans le bandeau en haut de page) au sein de laquelle vous initialisez une liste L2
de votre choix et en s'entraînant à accéder à n'importe laquelle des sous-listes possibles.
** Attention ** : Respecter l'affectation de ce nom (L2
) à la liste que vous allez créer, sans quoi les indications du paragraphe 3.2 ne coincideront plus avec la liste L1
sur laquelle nous continuons de travailler !
Souvenez-vous qu'il est toujours possible de supprimer une ou des cellules qui ont été créées en utilisant 'Edit -> Delete Cells' ou bien la 'paire de ciseaux' des icônes ci-dessus.
Il est aussi possible de réinitialiser l'ensemble des cellules, en allant dans l'onglet 'Kernel' et en exécutant 'Restart & Clear Output'.
Nous rappelons que les listes sont des objets * mutables *.
Si on connaît l'index d'un élément, il est facile de le changer ou de le remplacer.
Par exemple :
print(L1)
L1[1] = L1[1]+12
print(L1)
[1, 2, 3.5, '7', -2.4, 'test'] [1, 14, 3.5, '7', -2.4, 'test']
Vous avez dû obtenir en deuxième ligne : [1, 14, 3.5, '7', -2.4, 'test']
Il est aussi possible de modifier le ** type ** des éléments de la liste grâce à des "built-in function", qu'on appellera aussi des ** méthodes ** ou fonction primitives. On trouvera parmis celles-ci int()
, float()
, complex()
, str()
ou encore list()
, set()
.
Par exemple, pour remplacer le caractère "7"
par l'entier "7" on fera :
L1[3]=int(L1[3]) # on écrira float(L1[3]) pour le transformer en type float.
print(L1)
[1, 14, 3.5, 7, -2.4, 'test']
type(L1[3])
int
Exemple d'application de ces méthodes de changement de type (d'après Programmation en Python pour les mathématiques, par A. Casamayou-Boucau, P. Chauvin et G. Connan, (Dunod, 2012), p.38) :
Calculer $u_n=\cfrac{C_n}{n(n+1)}$ où $C_n$ désigne le nombre de chiffres intervant dans l'écriture décimale de $n$.
n = 53
print('u_',str(n),' vaut :',len(str(n))/(n*(n+1)))
u_ 53 vaut : 0.0006988120195667365
Plus généralement, il est particulièrement important de savoir manipuler une liste pour insérer, supprimer un élement, ou encore concaténer des listes.
Utilisez la ligne de code ci-dessous pour tester des méthodes particulièrement efficaces dont voici quelques exemples :
L1.append(14) # ajout de 6 en fin de liste
print(L1)
L1 = L1+[14] # autre méthode possible...
print(L1)
[1, 14, 3.5, 7, -2.4, 'test', 14] [1, 14, 3.5, 7, -2.4, 'test', 14, 14]
L1.insert(3,54) # insertion de x=54 à la position i=3
print(L1)
[1, 14, 3.5, 54, 7, -2.4, 'test', 14, 14]
L1.index(54) # retourne l'index de la première occurence de x=54
3
L1.count(14) # dénombre les x=14 présents dans L1 - essayer avec d'autres valeurs...
3
del L1[6:] # suppression des termes indexés à partir de 7
print(L1)
[1, 14, 3.5, 54, 7, -2.4]
L1.sort() # tri croissant de L1
print(L1)
L1.sort(reverse = True)
print(L1) # tri décroissant
[-2.4, 1, 3.5, 7, 14, 54] [54, 14, 7, 3.5, 1, -2.4]
Attention On rappelle que les listes sont des objets mutables. En particulier toute méthode appliquée à une liste ne créé pas un objet nouveau mais la modifie. Vos données d'origine sont perdues !
Aussi, dans le cas du tri d'une liste, si on ne souhaite pas perdre la liste de départ, on préfèrera L1_triee = sorted(L1) qui fait une copie triée de L1 sans la modifier.
Voyons maintenant les moyens de faire la ** copie ** d'une liste - la copie * superficielle * puis la copie * profonde * :
L = [1,[2,3]]
M = list(L) # copie superficielle: M est un nouvel objet `list` initialisé par L
M[0]=10
print(L,M)
M[1][0]=20
print(L,M)
[1, [2, 3]] [10, [2, 3]] [1, [20, 3]] [10, [20, 3]]
Si tout se passe bien pour M[0]
, le problème pour M[1][0]
vient du fait que M[1] pointe vers une même liste que L[1]...
Reprenons :
L = [1,[2,3]]
from copy import deepcopy
M = deepcopy(L) # copie profonde : M est une copie complète de l'objet référencé par L
M[0]=10
print(L,M)
M[1][0]=20
print(L,M)
[1, [2, 3]] [10, [2, 3]] [1, [2, 3]] [10, [20, 3]]
Création d'une liste de nombres à l'aide de la fonction range()
:
Cette fonction génère par défaut une séquence de nombres entiers de valeurs croissantes à partir de 0.
Cette séquence peut s'utiliser directement (par exemple pour une boucle POUR
) ou bien être transformée en liste :
list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for k in range(10):
print(k**2,end = " ")
0 1 4 9 16 25 36 49 64 81
Mais bien d'autres possibilités s'offrent à vous :
list(range(2,12))
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
list(range(2,12,2))
[2, 4, 6, 8, 10]
list(range(7,-5,-1))
[7, 6, 5, 4, 3, 2, 1, 0, -1, -2, -3, -4]
[0]*10
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[4,8,'bip']*3
[4, 8, 'bip', 4, 8, 'bip', 4, 8, 'bip']
list(range(5))*2
[0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
On peut aussi créer des listes "en compréhension" :
L = [k**2 for k in range(11)]
print(L)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
L2 = [k**2 for k in range(11) if k%2 == 0]
print(L2)
L3 = [k**2 for k in range(11) if (k > 4) and (k%2 == 0)]
print(L3)
[0, 4, 16, 36, 64, 100] [36, 64, 100]
Et même créer des listes de listes, utiles pour constituer des tableaux ou des matrices :
L4 = [[i**2+j for i in range(3)] for j in range(2)]
print(L4)
print('la première ligne vaut : ',L4[0])
print('la seconde ligne vaut : ',L4[1])
print('le deuxième terme de la première ligne vaut : ',L4[0][1])
Si on possède deux listes de même longueur, il est possible de les associer pour former des couples (appelés aussi tupples
) :
Couleur = ['carreau','coeur','pique','treffle']
Hauteur = ['Roi','Dame','Valet','As']
for (c,h) in zip(Couleur,Hauteur):
print(h,' de ',c)
ou encore, si on souhaite faire le produit scalaire de deux vecteurs $u$ et $v$ :
u = [1,0,2]
v = [-1,1,3]
print(sum(x*y for x,y in zip(u,v)))