Introduction au Python pour le calcul scientifique en mécanique

Ces notes de cours s'adressent à des étudiants ayant déjà des notions de programmation. Les concepts de typage des variables (entiers, réels, complexes, logiques...), d'affectation de variable, de tableaux, de boucles, de tests sont supposés connus. Il en est de même sur la manipulation d'algorithmes élémentaires. Nous ne revenons donc pas sur ces notions mais décrirons la manière de les implémenter en Python.

Dans cette UE, nous avons choisi d'utiliser Python 3. Il faut juste savoir que la version 2 de Python existe toujours. Nous mentionnons son existence car de nombreux exemples de codes se trouvent sur le web en Python 2. Il faut alors adapter la syntaxe qui diffère parfois.

Si vous souhaitez installer python chez vous, privilegiez la distribution anaconda qui est très simple d'installation. https://www.anaconda.com/products/individual Vous pouvez retrouver plus d'explications pour l'installation sur la page moodle du cours. Si vous avez peu de place sur votre disque dur prenez miniconda.

Il y a deux modes principaux d'utilisation de python :

  • Un mode interactif
  • Un mode script

Nous allons utiliser spyder. Spyder est IDE (Integrated Development Environment). C'est une sorte d'éditeur amélioré pour développer du code. On écrit un ensemble d'instructions dans des fichiers (appelés scripts) que l'on peut sauvegarder sur son disque dur. L'extension du fichier est .py

Pour accéder au mode interactif, on se place dans une console ipython. Cela ressemble à une calculatrice sophistiquée. La console est une fenètre intégrée dans spyder. On peut ainsi tester rapidement et simplement l'effet d'une commande ou faire de petits calculs.

Il existe aussi un environement très populaire appelé jupyter notebook. Les notebooks permettent de mélanger dans un même document du code, des textes, des figures, des vidéos, des liens vers des sites internet etc. Cela peut être très pratique pour la rédaction de document et pour communiquer des résultats scientifiques. L'extension du fichier est alors .ipynb. Par exemple, ce cours a été rédigé à l'aide d'un jupyter notebook puis exporté au format html. Vous n'utiliserez pas les notebooks dans cette UE.

Le typage des données et les variables:

En python, le typage des données est dynamique et se fait au moment de l'affectation de la donnée dans une variable. Par exemple, chacune des instructions ci-dessous

In [1]:
a = 5.3
compteur = 5
Nom_UE = "Outils informatiques pour la mécanique"
z = 1 + 5j
MonLogique = (3 < 5)

fait les opérations suivantes.

  • réserve de l'espace en mémoire
  • décide du type de la donnée
  • affecte la valeur de la donnée à droite du signe "=" à la variable à gauche de ce signe.

On peut le vérifier à l'aide de l'intruction print et type.

In [2]:
print(a)
type(a)
5.3
Out[2]:
float

a est donc un float c-à-d un réel qui vaut 5.3.

Dans spyder, on peut regarder les variables dans la fenêtre "explorateur de variables". C'est ce qu'il y a de plus pratique.

Alternativement, dans la console ipython, la commande whos permet d'afficher l'ensemble des variables utilisées en mémoire et leur type.

In [3]:
whos
Variable     Type       Data/Info
---------------------------------
MonLogique   bool       True
Nom_UE       str        Outils informatiques pour la mécanique
a            float      5.3
compteur     int        5
z            complex    (1+5j)

Les principaux types de données et les noms de variable :

Les principaux types sont les booléens, chaines de caractères str, les réels float, les entiers int et les complexes complex. Le nom des variables est assez libre mais comme dans tous les langages, il faut choisir des noms pertinents pour faciliter la lecture du code. Contrairement à certains langage comme le fortran, Python est sensible à la casse, il distingue donc les majuscules des minuscules. Il ne faut pas utiliser les mots clés de python comme nom de variable. La liste des mots-clés peut être connue en enchainant les deux commandes suivantes : import keyword et print(keyword.kwlist). Vous pouvez constater qu'il y en a très peu.

Les principaux opérateurs et l'ordre de priorité.

Priorité des opérateurs ( de la plus élevée à la plus basse) Description :
$**$ Elever à la puissance
$* \quad / \quad \% \quad \textrm{//} $ Multiplier, diviser, modulo et division entière
$+ \quad -$ Addition et soustraction
$ \textrm{ and not or } $ Opérateurs logiques
$<= \quad < \quad > \quad >= $ Opérateurs de comparaison
== != Opérateurs d'égalité
$= \quad -= \quad += \quad *= $ Opérateurs d'affectation

Il y a beaucoup d'erreurs liées à une méconnaissance des priorités des opérateurs ! En cas de doute, il faut mettre des parenthèses.

Les commentaires

Le symbole # sert à commenter une ligne.

Un bloc de lignes peut être commenté en commençant et en finissant par une ligne avec " " " (trois guillemets).

# Cette ligne a été commentée

""" 
Ces deux lignes 
sont commentées
"""

Les fonctions

Version simplifiée et compacte avec le mot clé lambda (très utile pour des fonctions mathématiques)

In [4]:
f = lambda x : x**2 + 1   # version avec une variable
g = lambda x,y : x**2 + y # version avec deux variables 
In [5]:
print(f(3))
print(g(3,2))
10
11

Version classique et plus générale avec le mot clé def

In [6]:
def EnergieCin(m,v):
    Ec = 1./2.*m*v**2
    print('Energie cinétique = ', Ec, 'J')
    # Notez l'indentation qui est significative en Python. En général on prend 4 espaces. 
    return # pas obligatoire si on ne renvoie rien. Ce n'est pas le return qui ferme la définition de la fonction.

EnergieCin(80,5) # Ici j'appelle la fonction EnergieCin avec les deux paramètres 80 et 5.
#print(Ec) # Produit une erreur car Ec n'est pas connu. C'est une variable interne à la fonction.
Energie cinétique =  1000.0 J

Il faut bien noter la syntaxe de la fonction :

  • Le mot clé def puis le nom de la fonction, suivi d'arguments entre parenthèse et séparés par des virgules et la présence des ":" au bout de la première ligne
  • un bloc d'instructions INDENTÉ (ici 4 espaces)

Il faut impérativement respecter cette syntaxe. L'indention est très importante. Contrairement à beaucoup de langage, l'indentation n'est pas utilisée par souci de lisibilité, elle est significative et fait parti du langage. La définition de la fonction est terminé quand on arrète d'indenter. Dans cette première fonction, le return n'est pas obligatoire ici car la fonction ne renvoie rien mais c'est mieux de le mettre.

Remarque : La variable interne Ec n'est pas connue en dehors de la fonction

Version avec renvoi de résultat et notion d'argument facultatif.

En général, on souhaite que la fonction renvoie le résultat du calcul pour s'en servir ailleurs.

In [7]:
def EnergieCin_new(m,v):
    Ec = 1./2.*m*v**2
    return Ec
# Cette fois EnergieCin-new renvoie la valeur Ec
masse = 80
vitesse = 4
EcHomme  =  EnergieCin_new(masse,vitesse) # EcHomme prend la valeur qui a été renvoyée par la fonction 

print('Energie cinétique Homme = ', EcHomme, 'J')

def Energies(m,v,h,g=9.81):  # g est un argument facultatif avec une valeur par défaut.
    Ec = 1./2.*m*v**2
    Ep = m*g*h
    return Ec,Ep # La fonction peut renvoyer plusieurs valeurs.
hauteur = 10
EcHomme, EpHomme = Energies(masse,vitesse,hauteur) # sans préciser g, la fonction prend la valeur par défaut
print('Energie potentielle Homme = ', EpHomme, 'J')
Energie cinétique Homme =  640.0 J
Energie potentielle Homme =  7848.000000000001 J

Sur la Lune, le résultat est différent pour l'énergie potentielle

In [8]:
gravite_Lune = 1.62
EcHomme, EpHomme = Energies(masse,vitesse,hauteur,gravite_Lune)
print('Energie cinétique Homme = ', EcHomme, 'J')
print('Energie potentielle Homme = ', EpHomme, 'J')
Energie cinétique Homme =  640.0 J
Energie potentielle Homme =  1296.0000000000002 J
In [9]:
# Affectation de plusieurs variables sur une ligne. C'est pratique mais trop limité si on a un grand nombre d'éléments.
a , b, c  = 1.5, "chien", 4<5
print(a,b,c)
1.5 chien True

Les conteneurs (objets itérables)

Le conteneur est une généralisation du tableau que vous connaissez déjà probablement. Le principal intéret des conteneurs est de pouvoir mélanger dans un même "tableau" des éléments avec différents types. Il y a trois conteneurs principaux dans le python de base :

  • les listes
  • les tuples
  • les dictionnaires.

Nous introduisons briévement ici uniquement les deux premiers: les listes et les tuples. Dans ce cours, nous les utiliserons peu.

Les listes et les tuples sont des collections ordonnées de variables pouvant être hétérogènes (mélange des types).

Les listes sont modifiables. Les tuples sont non modifiables.

Liste et tuple sont des objets itérables (appelés parfois séquences), c-à-d que l'on peut faire des boucles pour les parcourir.

Ces notions vont être plus claires à travers quelques exemples.

Liste : création et accès aux éléments

Les listes sont délimités par des crochets [ ] et les éléments séparés par une virgule,.

In [10]:
mescouleurs  = ["rouge","vert","bleu"] # ici la liste est homogène
autreliste   = ["rouge", 18, "vert", 22 ,"bleue", 43.5, 3<5 , True, 28.3] # La liste est hétérogène

print(autreliste[1]) # 

print(autreliste[0]) # J'affiche le premier élément de la liste

autreliste[3] = "cyan" # Je remplace un entier par une chaine de caractère

print(autreliste) # Affiche toute la liste

print(autreliste[-1]) # Affiche le dernier élément de la liste. 

unelistevide = []

Maliste2liste = [mescouleurs,autreliste]

print(Maliste2liste)
18
rouge
['rouge', 18, 'vert', 'cyan', 'bleue', 43.5, True, True, 28.3]
28.3
[['rouge', 'vert', 'bleu'], ['rouge', 18, 'vert', 'cyan', 'bleue', 43.5, True, True, 28.3]]

On note ici que les éléments des listes (ou tuples) sont repérés par des entiers qui commencent à 0 comme en langage C et non à 1 comme en matlab ou fortran. Le dernier élément est repéré par -1. L'avant dernier par -2 etc..

Manipulation de liste : Insertion et suppression d'éléments

In [11]:
autreliste   = ["rouge", 18, "vert", 22 ,"bleue", 43.5, 3<5 , True, 28.3] 
del(autreliste[3])  # je supprime le quatrième élément de la liste.

autreliste.insert(2,"noir") # j'ajoute un élément "noir" avec l'indice 2 dans la liste  
autreliste.append(66.4) # j'ajoute à la fin de la liste 66.4

print(autreliste)

# Une combinaison souvent utilisée
liste_1 = [] # On commence par une liste vide
liste_1.append(4) # On ajoute des éléments avec .append
liste_1.append('oiseau')
print(liste_1)
['rouge', 18, 'noir', 'vert', 'bleue', 43.5, True, True, 28.3, 66.4]
[4, 'oiseau']

Tuple : création et accès aux éléments

Les listes sont délimités par des parenthèses ( ) et les éléments séparés par une virgule,.

In [12]:
# Je crée un tuple : Bien noter les ( ) au lieu des [ ] 
couleursdrapeau = ("bleu","blanc","rouge")  

# Je peux connaître le nombre d'éléments d'une liste ou tuple avec la fonction len
len(couleursdrapeau)

# Comme pour une liste ou un tuple on accède au dernier élément avec l'indice -1, l'avant dernier avec -2 etc
couleursdrapeau[-2]
Out[12]:
'blanc'

L'accès aux éléments se fait aussi avec des crochets [ ] comme pour les listes

>>> couleursdrapeau[1] = "noir" 

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-7fa94d11d4d6> in <module>
----> 1 couleursdrapeau[1] = "noir"

TypeError: 'tuple' object does not support item assignment

Cette commande engendre une erreur car le tuple n'est pas modifiable. De même, l'instruction del(couleursdrapeau[1]) aurait provoqué une erreur.

Les instructions de contrôle

En général, on utilise les intructions de contrôle dans des scripts. Il faut utiliser un éditeur ou un IDE comme spyder pour les écrire. Les scripts sont sauvegardés avec l'extension .py. Une fois que la succession de commandes sont dans le script monscript.py, il est possible de l'exécuter en tapant python monscript.py dans un terminal ou en cliquant sur le triangle vert dans spyder. Un script exécute les instructions en séquence de haut en bas. Les instructions peuvent être répétées (boucles) ou éxecutées sous conditions (les tests).

La syntaxe pour ces instructions composées est particulière au python car l'indentation des lignes est significative (comme pour la définition des fonctions avec def).

Il y a :

  • une ligne d'introduction avec un mot-clé terminée par le caractère deux points :
  • un bloc d'instructions indenté par rapport à la ligne d'introduction. Il est d'usage de mettre 4 espaces pour faire cette indentation.

Les instructions de contrôle : Les tests

Les tests se font avec les mots clés if, elif et else.

  • Les comparateurs sont classiques >, <, >= (supérieur ou égal), <= (inferieur ou égal), == (égalité) et != (différent).
  • Les opérateurs booléens sont and, not, or.

Voici un exemple d'utilisation de if : bien observer les indentations !

In [13]:
x = 7
if x < 0 :
    print("x est strictement négatif")
elif x%2 !=0 :
    print("x est positif et impair")
else:
    print("x n'est pas négatif et est pair")
    
if x>= 5 and x<8:  # combinaison de conditions 
    print("x est tel que : 5 <= x < 8")
x est positif et impair
x est tel que : 5 <= x < 8

Les instructions de contrôle : Les boucles for

Les boucles for parcourent des itérables. C'est donc un peu plus général que les boucles parcourant simplement des indices. On peut ainsi parcourir directement une liste (ou un tuple) sans passer par les indices de la liste. Exemple :

In [14]:
for couleurs in mescouleurs:
    print(couleurs)
print("Toutes les couleurs sont imprimées")    
rouge
vert
bleu
Toutes les couleurs sont imprimées

Une chaine de caractères (str) est aussi un itérable car la variable est considérée comme une liste non modifiable de caractères.

In [15]:
Prenom = "Joséphine"
for lettre in Prenom:
    print(lettre)
J
o
s
é
p
h
i
n
e

La notion d'itérateur : range

Pour parcourir des indices comme avec des langages de plus bas niveau, on a recours à un "itérateur" appelé range. Il y a trois syntaxes possibles:

  • range(stop) génère des entiers allant de 0 à stop-1
  • range(start,stop) génére des entiers allant de start à stop-1
  • range(start,stop,step) génère des entiers allant de start à stop-1 avec un pas step.

Note : Il est aussi possible de créer des listes à partir de range et list:

In [16]:
maliste = list(range(2,9,2))
print(maliste)
[2, 4, 6, 8]

Exemples de boucles avec range :

In [17]:
for i in range(5):
    print(i)
print("Démarre à 0 et finit à  4 !")    
0
1
2
3
4
Démarre à 0 et finit à  4 !

Boucle interrompue par l'instruction break:

In [18]:
for i in range(2,17,3):
    if i>11:
        break  
    print(i, end=" ") # Le end=" " remplace le retour à la ligne du print() par un espace.
print(" La boucle est interrompue pour i stritement supérieur à 11")
print(i)
2 5 8 11  La boucle est interrompue pour i stritement supérieur à 11
14

Boucle utilisant l'instruction continue:

In [19]:
for i in range(2,20,3):
    if i==8:
        continue  
    print(i, end=" ") # Le end=" " remplace le retour à la ligne du print() par un espace.
print(" La boucle a sauté la valeur 8 ")
print("En sortie de boucle la valeur de i vaut :",i)
2 5 11 14 17  La boucle a sauté la valeur 8 
En sortie de boucle la valeur de i vaut : 17

Les instructions de contrôle : Les boucles while

Les boucles while répetent des instructions tant qu'une condition est vérifiée. Exemple :

In [20]:
x = 0

while (x<10):
    print(x)
    x +=1
0
1
2
3
4
5
6
7
8
9

Ajout de fonctions supplémentaires avec import

Python est assez rudimentaire et très peu de fonctions sont connues. On peut ajouter des modules (ou bibliothèques) avec la fonction import.

Pour avoir accéder aux fonctions mathématiques classiques, on importe la bibliothèque math import math puis on précéde le nom de la fonction du nom de la bibliothèque séparé par un point par exemple math.log(4.5) math.pi

Pour manipuler les complexes on importerait cmath

In [21]:
import math
import cmath # Importe les fonctions math pour manipuler les complexes

math.log(4.5)
print(math.pi)
print(cmath.sqrt(-1))
# print(math.sqrt(-1)) provoque une erreur
# dir(math) pour voir les fon
3.141592653589793
1j

A propos des listes:

Les listes ne sont pas forcément très performantes et pratiques quand il s'agit de faire du calcul scientifique. Pour remédier à cela, des modules ont été crées. Les principaux modules pour le calcul scientifique sont numpy et scipy. Pour générer des graphiques, la bibliothèque standard est matplotlib