Introduction à Python (2.7) pour le Calcul Scientifique

Ceci est une brève introduction au langage python (et son notebook) que nous allons utiliser en vue de coder des méthodes pour le cours de calcul scientifique.

Python est en réalité un véritable langage de programmation développé depuis 1990 dont l'intérêt dépasse le calcul scientifique. C'est un langage dit de «haut niveau» qui est multi-plateforme (Windows, macOS, Unix) et multi-paradigme (prog impérative, fonctionnelle, orientée objet).

Il est distribué sous license libre et gratuit, ce qui ne gâche rien :)

Voici une liste d'organisations utilisant Python: https://wiki.python.org/moin/OrganizationsUsingPython

1. les variables simples

Comme en mathématiques, tout langage de programmation manipule des variables dont voici quelques exemples:

In [1]:
A = 2
B = "ceci est une chaine de caractères"
C = 3/4
D = 9,2333
E = 9.2333
In [2]:
print A,B,C,D,E
2 ceci est une chaine de caractères 0 (9, 2333) 9.2333

Pour comprendre comment cela fonctionne, il est important de connaître la nature des variables, c'est-à-dire leur type.

In [3]:
print type(A), type(B), type(C),type(D), type(E)
<type 'int'> <type 'str'> <type 'int'> <type 'tuple'> <type 'float'>

La variable C est un entier, car l'opérateur / réalise en fait la division euclidienne entre deux entiers. Pour s'en convaincre:

In [4]:
print 19/4 
4

Comment calculer la vraie division réelle ? on remplace un entier par le réel qui lui correspond:

In [5]:
print 19.0/4
4.75

En ce qui concerne D, c'est un tuple, une variable composée, qui est en réalité le couple (9,2333). Nous y revenons plus bas.
Pour écrire des nombres à virgule, il faut donc utiliser la notation ".", par exemple : 2.127

2. Utilisation de fonctions

Essayons de calculer un cosinus:

In [6]:
print cos(E)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-6-aeabdfe73609> in <module>()
----> 1 print cos(E)

NameError: name 'cos' is not defined

La fonction "cos" n'est pas définie par défaut, il faut donc importer une bibliothèque de fonctions.
Pour le calcul scientifique, nous utiliserons essentiellement deux bibliothèques:

  • numpy, pour les fonctions, variables scientifiques
  • matplotlib, pour les représentations graphiques

Voici comment importer l'ensemble de toutes les fonctions d'une bibliothèque:

In [7]:
from numpy import *
In [8]:
print cos(E), E**3, E/3, e
-0.981724036652 787.17417829 3.07776666667 2.71828182846

Le symbole ** calcule la puissance;
ici E/3 ne renvoit pas un entier car E n'est pas un entier ;
enfin, les majuscules ont leur importance : e est la base de l'exponentielle, qui est définie comme variable dans la bibliothèque !

In [9]:
print e**(1/2), e**(1.0/2)
1.0 1.6487212707

On peut également n'importer que les fonctions/variables souhaitées, pour optimiser les importations:

In [10]:
from numpy import cos, tan, pi
print cos(pi), tan(0)
-1.0 0.0

Remarque — Voir dans les compléments une autre façon d'importer une bibliothèque, et d'appeler les fonctions, variables, objets de ces bibliothèques (notation pointée)

3. Variables composites

3.1 Les tuples

Nous avons rencontré plus haut un premier type de variable composite, le tuple, qui est une généralisation du couple, qui est une collection de variables séparées par des virgules. Les parenthèses ne sont pas obligatoires, mais c'est sans doute préférable pour la lecture au moins au début:

In [11]:
A = (2, 9, "test", e, 3.0/2)
B = 3, 12
print A, B
(2, 9, 'test', 2.718281828459045, 1.5) (3, 12)

On le voit, un tuple peut contenir n'importe quel type de variable, y compris un tuple lui-même :

In [12]:
C = (A, B)
print C
((2, 9, 'test', 2.718281828459045, 1.5), (3, 12))

On peut accéder à un élément spécifique d'un tuple par son indice, sa position dans le tuple.

Attention — en python, par défaut tous les indices commencent à zéro !

In [13]:
print A[1],"hop", A[0]
9 hop 2

Si on peut accéder à n'importe quel élément d'un tuple, on ne peut le modifier.
C'est d'ailleurs un intérêt de ce type de données, qui est ainsi protégée:

In [14]:
A[2] = 3
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-58f4790c05f7> in <module>()
----> 1 A[2] = 3

TypeError: 'tuple' object does not support item assignment

Note — les tuples sont très souvent utilisés pour initialiser plusieurs variables en une seule ligne:

In [15]:
(a,b,c) = (2,"blabla",pi)
print a,c
2 3.14159265359

ce qu'on réduit souvent sans parenthèses:

In [16]:
a,b,c = 2,"blabla",pi
print b
blabla

3.2 Les listes

Les listes ressemblent beaucoup aux tuples, mais elles sont modifiables. On les déclare avec des crochets.

In [17]:
liste = [ 2, "toto", A, 3.2 ]
print liste
[2, 'toto', (2, 9, 'test', 2.718281828459045, 1.5), 3.2]
In [18]:
liste[2] = 0
print liste
[2, 'toto', 0, 3.2]

En pratique, on utilisera souvent les listes pour manipuler des objets, par exemple des matrices.
Les tuples sont utilisés pour passer des paramètres aux fonctions, cf. ci-dessous.

Note — une chaîne de caractères (string) est en fait un type composite, cf. compléments.

3.3 Techniques de slicing

Il s'agit d'une technique très utile pour accéder à plusieurs éléments d'une liste (ou d'un tuple).
Elle consiste à utiliser les deux points ":"

In [19]:
premiers = [1,3,5,7,8,11,13,17,19]
In [20]:
print premiers[0:3]
[1, 3, 5]
In [21]:
print premiers[3:]
[7, 8, 11, 13, 17, 19]
In [22]:
print premiers[:1]
[1]
In [23]:
print premiers[:]
[1, 3, 5, 7, 8, 11, 13, 17, 19]

Attention — la notation [a:b] renvoit les éléments de la position a (inclus) jusqu'à la position b (exclus)

4. Structures de contrôle

Les différentes structures de contrôle gèrent le flux des instructions, c'est-à-dire la façon dont elles s'enchaînent en fonction de certains tests ou boucles.

4.1 Bloc de code

La notion de bloc de code correspond à une hiérarchisation d'un programme : il s'agit de regrouper certaines instructions qui «vont ensemble», notamment quand elles sont exécutées si une certaine condition est remplie.

In [ ]:
bloc principal

if condition:
    ...
    (bloc 2)
    ...

    if condition2:
        ...
        (bloc 3)
        ...

    fin du bloc 2

fin du bloc principal

Dans les plupart des langages, les blocs de code sont délimités par des accolades (langage C, PHP, etc.).

En python, il n'y a pas de délimiteur spécifique, c'est l'indentation du code qui détermine les blocs ! C'est à la fois un avantage et un défaut: cela force à avoir un code proprement indenté, sans quoi il ne peut s'exécuter correctement. Mais il faut en prendre l'habitude.

4.2 Boucle for

Les boucles sont très utilisées en programmation, ne serait-ce que pour passer en revue des entiers.
On utilise pour cela la fonction range:

In [24]:
for i in range(4):
    print i
0
1
2
3

On aura noté que Python est cohérent sur le fait que les indices démarrent à zéro.
range(a) renvoit une liste de "a" éléments, commençant par zéro et finissant donc par... "a-1".

Note — on peut utiliser cette fonction de façon plus complexe, pour voir les utilisations diverses, utiliser le point d'interrogation qui appelle l'aide en ligne:

In [25]:
range?

La syntaxe spécifique se comprend par le fait que la boucle for permet d'itérer n'importe quelle liste (et plus généralement tous les objets "itérables"). Or, range fournit une liste.

In [26]:
R = range(10)
print type(R)
<type 'list'>
In [27]:
for entree in A:
    print entree
2
9
test
2.71828182846
1.5

Voici un exemple de code calculant les dix premiers termes de la suite de Fibonacci:

In [28]:
(a,b) = (0,1)    # intialisation

for i in range(10):
    # debut du bloc de code
    c = a + b
    print c
    (a,b) = (b,c)
    # fin du bloc de code    
1
2
3
5
8
13
21
34
55
89

On notera plusieurs choses:

  • l'utilisation de commentaires par le signe dièse #
  • l'affectation multiple sur une même ligne (très pratique!)
  • on a ajouté ici des commentaires pour marquer le début et la fin du bloc mais c'est inutile

4.3 Condition if

Il s'agit d'un test qui déclenche l'exécution d'un bloc si une condition est remplie.

In [29]:
a = 11      # initialisation

if a > 10 :    # test
    # début du bloc 
    print "a est plus grand que dix"
    # fin du bloc
a est plus grand que dix

On peut utiliser une syntaxe plus élaborée en disant quoi faire si le test échoue:

In [30]:
a = 9

if a > 10 :
    print "a est plus grand que dix"
elif a == 10:
    print "a est égal à dix"
else:
    print "a est plus petit que dix"
a est plus petit que dix

elif est l'équivalent de "else if ..." ; on pourrait en enchainer plusieurs pour traiter d'autres sous-cas ; enfin le bloc qui suit else est traité si aucun test n'a été validé en amont.

Note — on fera attention au test d'égalité qui utilise un double signe égal == ,
pour qu'il n'y ait pas de confusion avec l'affectation de valeur (a=b).

4.4 Condition while

Il s'agit ici d'exécuter une commande ou un bloc de code tant que (while) une certaine condition est remplie:

In [31]:
n = 6         # initialisation du nombre de départ
fact = 1      # intialisation de la factorielle
m = 0         # initialisation variable auxilliaire

while m != n:                 # test : si m différent de n
    m = m + 1                 # alors on ajoute 1
    fact = fact * m           # et on multiplie fact par m   

print "Factorielle de ", n, " = ", fact
    
Factorielle de  6  =  720

Note — on notera le double point ":" après chaque test ou boucle, qui détermine le début d'un bloc indenté juste après.

5. Fonctions

Nous avons déjà vu comment utiliser des fonctions, voyons maintenant comment en créer. L'intérêt est d'avoir nos propres fonctions, qui seront donc des bouts de code réutilisables.

Supposons par exemple que nous souhaitions calculer la factorielle de n'importe quel nombre entier à partir du code ci-dessus. Nous allons donc définir une fonction factorielle à l'aide du mot-clef def:

In [32]:
def factorielle(n):
    fact,m = 1,0     # initialisation       
    
    while m != n :
        m = m+1
        fact = fact*m
        
    return fact
In [33]:
print factorielle(7)
5040

On passe donc l'entier en paramètre et il en ressort un entier, la factorielle.

Note:Il faut cependant être prudent: si on n'envoit pas un entier à notre fonction, on risque des ennuis ! On peut donc améliorer notre fonction en testant le type de n dès le début du code.

La fonction suivante calcule le volume d'un pavé dont on donne les cotés:

In [34]:
def volume(largeur, longueur, hauteur):
    return largeur*longueur*hauteur
In [35]:
print volume(3,5,4)
60

En plus du type, il faut donc se souvenir de l'ordre des paramètres pour l'appel d'une fonction. Ceci étant, on peut utiliser les étiquettes pour éviter les ennuis:

In [36]:
print volume (longueur=2, hauteur=6, largeur=3)
36

On a utilisé ici deux fonctions qui renvoient quelque chose, à l'aide du mot-clef return.
Mais une fonction peut aussi ne rien renvoyer (en général, on préfère parler de méthode dans ce cas), comme par exemple:

In [37]:
a = [[0,0,1],[1,0,0],[0,1,0]]

def modify(a):
    a[1][1]=1

print a[1][1]

modify(a)

print a[1][1]
    
0
1

Conclusion

Nous n'avons évidemment fait que survoler (et de très haut) les bases du langage Python. Voici un résumé de l'essentiel à retenir pour le moment:

  • types de variables simples : entier, flottant, booléen, caractère
  • types de variables composées : tuples, listes, chaines de caractères
  • blocs de code : c'est l'indentation qui détermine le niveau du bloc
  • structures de contrôle du flux : for, if-elif-else, while
  • fonctions : on utilise les mots-clef def et return
In [ ]:
 
In [ ]:
 
In [ ]: