Programmation Scientifique avec Python

22
Programmation Scientifique avec Python Master 1 Physique-Chimie [email protected] 19 janvier 2007 Table des matières 1 Introduction 2 2 Installation de Python 3 3 Programmer avec Python 3 3.1 Ligne de Commande ou éditeur ? ............................... 3 3.2 Aide en ligne ......................................... 4 3.3 Variables et types de données élémentaires .......................... 4 3.3.1 Variables simples ................................... 4 3.3.2 Nombres complexes ................................. 4 3.3.3 Chaînes de caractères ................................. 5 3.3.4 Listes ......................................... 5 3.3.5 Tuple [Facultatif] .................................. 6 3.3.6 Dictionnaires [Facultatif] .............................. 7 3.3.7 Conversion de variables entre différents types .................... 7 3.4 Boucles et opérateurs ..................................... 7 3.4.1 opérateurs ==,and, or , not ........................... 7 3.4.2 L’instruction if...elif..else ......................... 8 3.4.3 La boucle while ................................... 8 3.4.4 Les boucles for ................................... 9 3.4.5 Exercice : décomposition en facteurs premiers .................... 9 3.5 Fonctions ........................................... 9 3.6 Portée des objets : variables locales et globales ....................... 10 3.7 Exercice ............................................ 11 4 Classes et Objets 11 4.1 Présentation .......................................... 11 4.2 Exemple ............................................ 12 4.3 Attributs ............................................ 12 4.4 Fonctions membres ...................................... 13 4.5 Fonctions membres spéciales [Facultatif] .......................... 13 4.5.1 Constructeur __init__ ............................... 14 4.5.2 Destructeur __del__ ................................ 14 4.5.3 Opérateurs __add__, __sub__, __mul__, __div__, __pow__ ....... 14 4.6 Héritage [Facultatif] ..................................... 14 4.7 Attention : opérateur “==”, différence entre égalité et identité, copie et référence... [Facul- tatif] ............................................. 15 4.8 Exercice ............................................ 16 1

description

A good and practical course on Python scientific programing in French.

Transcript of Programmation Scientifique avec Python

Page 1: Programmation Scientifique avec Python

Programmation Scientifique avec PythonMaster 1 Physique-Chimie

[email protected]

19 janvier 2007

Table des matières1 Introduction 2

2 Installation de Python 3

3 Programmer avec Python 33.1 Ligne de Commande ou éditeur ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33.2 Aide en ligne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43.3 Variables et types de données élémentaires . . . . . . . . . . . . . . . . . . . . . . . . . . 4

3.3.1 Variables simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43.3.2 Nombres complexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43.3.3 Chaînes de caractères . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.3.4 Listes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53.3.5 Tuple [Facultatif] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63.3.6 Dictionnaires [Facultatif] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.3.7 Conversion de variables entre différents types . . . . . . . . . . . . . . . . . . . . 7

3.4 Boucles et opérateurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.4.1 opérateurs ==,and, or , not . . . . . . . . . . . . . . . . . . . . . . . . . . . 73.4.2 L’instruction if...elif..else . . . . . . . . . . . . . . . . . . . . . . . . . 83.4.3 La boucle while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83.4.4 Les boucles for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.4.5 Exercice : décomposition en facteurs premiers . . . . . . . . . . . . . . . . . . . . 9

3.5 Fonctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.6 Portée des objets : variables locales et globales . . . . . . . . . . . . . . . . . . . . . . . 103.7 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

4 Classes et Objets 114.1 Présentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114.2 Exemple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124.3 Attributs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124.4 Fonctions membres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134.5 Fonctions membres spéciales [Facultatif] . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4.5.1 Constructeur __init__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144.5.2 Destructeur __del__ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144.5.3 Opérateurs __add__, __sub__, __mul__, __div__, __pow__ . . . . . . . 14

4.6 Héritage [Facultatif] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144.7 Attention : opérateur “==”, différence entre égalité et identité, copie et référence... [Facul-

tatif] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154.8 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

1

Page 2: Programmation Scientifique avec Python

5 Lecture et écriture de fichiers 165.1 Exercice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

6 Utilisation de “modules” (standards et librairies extérieures) 176.1 Modules de calcul scientifique . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

6.1.1 math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176.1.2 Scipy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176.1.3 Sous-modules de scipy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186.1.4 MatPlotlib/PyLab (http ://matplotlib.sf.net) . . . . . . . . . . . . . . . . . . . . . 196.1.5 Autres modules scientifiques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

7 Performance et interface C/C++ <-> Python [Facultatif] 207.1 Performance : C/C++ vs Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

7.1.1 Utilisation de scipy.weave . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217.2 Interface C/C++ <-> Python avec SWIG . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

1 IntroductionIl existe déjà un grand nombre de langages utilisés pour le calcul scientifique (C/C++/fortran), stabi-

lisés et développés depuis de nombreuses années. Pourquoi développer (et donc apprendre !) un nouveaulangage ? Il s’avère que les langages traditionnels sont soit inadaptés à une utilisation généraliste (calculs etcréation d’un interface graphique - ex : fortran), ou ont une syntaxe suffisamment complexe ou rigide pourrendre difficile son utilisation par un utilisateur occasionnel (c++). C’est ce qui a permis le succès de lo-giciels commerciaux spécialisés dans le calcul (Mathematica, Maple, Mathlab,...), et de langages (IDL,...),qui associent une syntaxe relativement simple avec des fonctionnalités (représentation graphique, librairiesde calcul) étendues, et utilisables directement à partir d’une ligne de commande (sans compilation préa-lable).

C’est pour pallier ce manque que le langage Python (http ://www.python.org) a été développé. Il pré-sente de multiples avantages par rapport aux langages traditionnels :

– naturel (utilisation de l’indentation, typage dynamique)– utilisable en ligne de commande (donc interactif )– moderne (orienté objet)– extensible (modules externes de calcul et de visualisation écrites en C/C++/fortran)– très utilisé pour le calcul scientifique (grâce à la réutilisation de librairies de calculs déjà existantes)– libre (“open-source”) et multi-plateforme (Linux, windows, MacOS,...)

Un désavantage apparent de python vient du fait qu’il s’agit d’un langage interprété, et donc plus lentqu’un langage compilé. Ce n’est pas un inconvénient majeur, car chaque fois qu’un calcul “intensif” estnécessaire, il est possible de l’effectuer dans un module externe écrit dans un autre langage, plus efficace.En général seule une petite partie d’un programme a besoin d’être vraiment optimisée (en général moinsde 5% du code représente 95% du temps de calcul !).

En outre, il s’avère que l’on passe souvent plus de temps à écrire un programme qu’à l’utiliser, cequi relativise l’importance de la “performance pure” du programme. L’intérêt de python est justementd’accélérer le développement d’un programme par sa syntaxe simple, et par sa capacité à réutiliser deslibrairies existantes.

Les différences fondamentales par rapport au C++ avec lesquelles il faut se familiariser sont :– C’est un langage interprété, utilisable avec une ligne de commande– Les “blocs” de code (ex : intérieur d’une boucle) sont identifiés par l’indentation (nombre d’espaces

en début de ligne), et non par des acollades {...}– Le type des objets (’int’, ’float’, ’string’) est dynamique, ç.à.d. qu’il n’a pas besoin d’être déclaré à

l’avance et qu’il peut être modifié au cours du programme.

2

Page 3: Programmation Scientifique avec Python

2 Installation de PythonSous Linux : Python est installé sur toutes les distributions, en standard - il est par contre nécessaire

d’ajouter des modules tels que SciPy et matplotlib, suivant le type de programme souhaité.Sous Windows : la distribution standard de python est disponible sur http ://www.python.org, mais il

est recommandé d’installer la version de python de la société Enthought (Enthought Python = Enthon), quiinclut les modules de calculs scientifique les plus utiles http ://code.enthought.com/enthon/.

3 Programmer avec Python

3.1 Ligne de Commande ou éditeur ?Python peut être utilisé à partir d’une ligne de commande (langage interprété). Pour lancer l’inter-

préteur, taper “python” dans une console linux, puis à l’invite de commande (“>>>”), taper “print“toto””. Cela donne

[vincent@localhost vincent]$ python Python 2.3.3 (#2, Feb 17 2004, 11 :45 :40)[GCC 3.3.2 (Mandrake Linux 10.0 3.3.2-6mdk)] on linux2Type "help", "copyright", "credits" or "license" for more information.

>>> print "toto"toto>>>

Dans un autre langage, il aurait fallu écrire le texte du programme dans un fichier, puis le compiler avantde l’éxécuter. En fait il est également possible d’écrire le programme dans un fichier. Pour cela ouvrir unéditeur de texte (par exemple nedit ou kate), écrire le programme (print “toto”), et le sauvegardersous le nom toto.py. Ensuite, éxécuter le programme avec la commande “python toto.py” à partird’une console Linux (il est également possible d’utiliser “python -i toto.py” afin de rester dansl’interpréteur après éxécution du programma). De fait, écrire un programme sur la ligne de commande oule taper au préalable dans un fichier avant de l’exécuter est rigoureusement équivalent.

Pour l’utilisation en ligne de commande, il est encore plus avantageux d’utiliser ipython : “ipythontoto.py” - c’est une version plus interactive de python, qui se souvient des instructions tapées lors dela dernière session ipython (utiliser les flèches haute et basse pour naviguer dans l’historique des com-mandes), et qui sait “compléter” les commandes (pour utiliser une fonction ou un objet, taper le début dunom et appuyer sur la touche tabulation - le nom sera complété ou différents choix seront proposés).

Voilà ! Vous savez programmer en Python. Dans la pratique, les tests rapides sont faits avec la ligne decommande, et les programmes longs sont écrits dans un fichier avant d’être exécutés.

Note 1 : pour sortir de l’interpréteur Python, taper ctrl-dNote 2 : le symbole # sert à commencer un commentaire en python. Tout ce qui se trouve sur une ligne

après un # n’est pas interprété par python :>>> print “toto” # ceci est mon premier programme en python!totoNote 3 : pour éxécuter des commandes dans un fichier texte depuis l’interpréteur python, il faut utiliser

la fonction execfile (e.g. execfile(“toto.py”))Note 4 : pour pouvoir utiliser des accents dans Python, il faut préciser l’encodage que nous utilisons,

en mettant au début du fichier python la ligne suivante :# -*- coding : iso-8859-15 -*-

3

Page 4: Programmation Scientifique avec Python

3.2 Aide en ligneTous les objets standards (de même que les modules correctement conçus) possèdent une aide en ligne,

qui peut ête invoquée avec la fonction help(). Par exemple help(str), help(list), permettentd’accéder à l’aide sur les chaînes de caractère et sur les listes. Lorsqu’un module est importé (e.g. ’importmath’), il est possible de lire l’aide correspondant à ce module (e.g. ’help(math)’) ou à une fonctionde ce module (e.g. ’help(math.sin)’).

Lorsque ipython est utilisé, c’est encore plus simple, il suffit de taper la commande suivie de un oudeux points d’interrogations (suivant le détail de la documentation souhaitée), par exemple : ’list?’.

3.3 Variables et types de données élémentaires3.3.1 Variables simples

Pour créer une variable, il suffit de lui affecter une valeur :>>> x=1>>> print x1On voit ici une différence importante avec d’autres langages : il n’est pas nécessaire de déclarer a priori

le type de la variable x (entier ’int’, nombre flottant ’float’, chaine de caractère ’string’,...). Pourtant ce typeexiste bien, si vous demandez ensuite :

>>> print type(x)<type ’int’>Python a donc automatiquement décidé que x était un entier (int = integer). Essayez avec d’autres

initialisations : “x=1.0” (nombre flottant ou float), “x=”bonjour”” (chaine de caractère ou string),...Il est à noter qu’il est possible de changer le type de x en lui affectant des valeurs différentes :>>> x=57>>> type(x)<type ’int’>>>> x="Astérix">>> type(x)<type ’str’>>>> x=3.14159263>>> type(x)<type ’float’>

Bien que cela soit pratique, cela peut entraîner des erreurs de programmation, donc dans la mesure dupossible il faut toujours utiliser des noms de variables explicites (age sera un entier, nom une chaînede caractères, etc...), et ne pas changer de type en cours de programme.

Attention : majuscules et minuscules sont différenciées par python, i.e. mavariable, MAVARIABLEet MaVariable sont trois variables distinctes. Il en va de même pour tous les mot-clefs et les fonctionsen python.

3.3.2 Nombres complexes

Il est possible de manipuler des nombres complexes en Python, le nombre complexe “i” étant noté j :>>> a=2+1j>>> type(a)<type ’complex’>>>> b=3.5+4j>>> print a+b(5.5+5j)>>> print a*b

4

Page 5: Programmation Scientifique avec Python

(3+11.5j)Pour utiliser des fonctions mathématiques sur des complexes, il faudra importer le module cmath enplus du module math (voir la section sur l’utilisation de modules), ou bien le module scipy qui inclutégalement les tableaux.

3.3.3 Chaînes de caractères

Outre l’attribution simple (maChaine=”Toto”), il est possible d”’écrire” une chaîne de caractère dela même manière qu’avec la fonction printf classique, c’est à dire en insérant des codes dans la chaîne(%s pour une chaîne de caractères„ %d pour un entier, %f pour un nombre réel, avec éventuellement lenombre de caractère total et après la virgule : %4.2f veut dire ’nombre réel représenté sur 4 caractères,avec 2 chiffres après la virgule’), suivie de % avec entre parenthèses toutes les variables dont les valeurssont à insérer :

>>> age=5>>> nom="Vincent">>> taille=1.73>>> maChaine="%s a %d ans et mesure %4.2f m"%(nom,age,taille)>>> print maChaineVincent a 5 ans et mesure 1.73 m

Il est possible d’extraire des caractères d’une chaîne :>>> print maChaine[2 :6] # extrait les caractères 2 à 6 (exclu)ncen

Par contre il n’est pas possible de modifier de cette manière une sous-chaîne de caractère : maChaine[2 :6]=”tapl”génère une erreur.

Il est possible d’additionner des chaînes de caractères :>>> print "Programmation" + " Scientifique"Programmation ScientifiqueOn peut obtenir la longueur d’une chîne de caractère avec la fonction len().>>> len("toto")4

help(str) donne la liste des fonctions utilisables avec des chaînes de caractères.

3.3.4 Listes

Un type particulièrement intéressant est la liste :>>> x=[1,4,32]>>> print x[1, 4, 32]>>> print type(x)<type ’list’>>>> print x[2]32

Attention ! On voit ici que la numérotation des objets de la liste commence à 0 (i.e. si il y a n élémentsdans liste, ils sont accessibles par liste[0]...liste[n-1]).

Une liste peut contenir des objets de types différents, contrairement à un tableau :>>> liste=[1,"Obélix",57.0]>>> print liste[0]1

5

Page 6: Programmation Scientifique avec Python

>>> print liste[1]Obélix>>> print liste[2]57.0>>> print type(liste[0]),type(liste[1]),type(liste[2])<type ’int’> <type ’str’> <type ’float’>

Il est possible de modifier une liste existante :MaListe[1]=42 # le 2ème élément de MaListe vaut maintenant 42MaListe.append(45) # ajoute l’objet “42” à la fin de la listeMaListe.insert(i,x) # insère l’élément x à l’indice i dans MaListe

MaListe.reverse() # inverse l’ordre des éléments de la listeMaListe.sort() # trie les éléments de la liste par ordre croissant

On peut obtenir la longueur d’une liste (le nombre d’objets dans la liste) avec la fonction len() :len(MaListe).

Il est possible de concaténer deux listes avec l’opérateur + :>>> liste1=[1,"ab",3.5]>>> liste2=["toto",57]>>> print liste1+liste2[1, ’ab’, 3.5, ’toto’, 57]

On peut également supprimer un élément d’une liste avec la fonction del() :>>> liste=[1, ’ab’, 3.5, ’toto’, 57]>>> print liste[1, ’ab’, 3.5, ’toto’, 57]>>> del(liste[1])>>> print liste[1, 3.5, ’toto’, 57]

Les listes sont des objets particulièrement importants car les boucles utilisent souvent une itérationsur des éléments d’une liste. La liste complète des fonctions utilisables pour une liste peut être obtenueavec l’aide help(list). Il existe en particulier une fonction de tri sort() : essayez-la sur une liste denombres (entiers et réels mélangés).

3.3.5 Tuple [Facultatif]

Un tuple est un objet similaire à une liste, la principale différence étant qu’un tuple ne peut pas être mo-difié partiellement. C’est une liste d’objets séparés par des virgules ; on peut (mais ce n’est pas obligatoire)encadrer ces objets par des parenthèses pour mieux délimiter le tuple :

>>> monTuple=(’a’,"toto",54.2)>>> type(monTuple)<type ’tuple’>

Il est possible d’extraire un ou plusieurs objets d’un tuple :>>> print monTuple[1]toto>>> print monTuple[1 :3](’toto’, 54.200000000000003)

Par contre il n’est pas possible de modifier un objet dans un tuple (monTuple[1]=”tata” est uneinstruction illégale), ou d’ajouter des éléments dans un tuple.En général on ne crée pas explicitement de variable de type tuple, mais ce sont des variables qui aparaissentde manière temporaire, lorsqu’on veut manipuler ensemble plusieurs objets :

6

Page 7: Programmation Scientifique avec Python

>>> a,b=5,3 #création de deux variables en une seule ligne>>> print a,b5 3>>> a,b=b,a # échange de deux variables>>> print a,b3 5

3.3.6 Dictionnaires [Facultatif]

Un dictionnaire est également un type de liste d’objet, mais au lieu de repérer les objets par un indicecommençant à 0, les différents objets sont accessible à l’aide d’une clef, qui peut être un objet quelconque.(pour les personnes familières avec la librairie standard du C++, c’est l’équivalent de std : :map<>).

>>> fra_deu={"un" :"ein","trois" :"drei","deux" :"zwei"} # Création>>> fra_deu["trois"] # Accès à un élément du dictionnaire’drei’>>> fra_deu["quatre"] # Clef n’existant pas!Traceback (most recent call last) :File "<stdin>", line 1, in?

KeyError : ’quatre’>>> fra_deu["quatre"]="vier" # Ajout de l’entrée manquante>>> fra_deu["quatre"]’vier’

Vous pouvez obtenir les différentes fonctions disponibles pour un dictionnaire avec la comande help(dict).

3.3.7 Conversion de variables entre différents types

On peut convertir une variable d’un type à un autre :>>> x=float(1) # nombre réel à partir d’un entier>>> print type(x)<type ’float’>>>> x=float("1.0") # nombre réel à partir d’une chaîne de caractère>>> print type(x)<type ’float’>>>> print x1.0

3.4 Boucles et opérateurs3.4.1 opérateurs ==,and, or , not

L’opérateur == permet de comparer deux objets :>>> 1==2 # est-ce que 1 est égal à 2?False>>> 1==1TrueLes autres opérateurs de comparaison sont <, >, <=, >=, !=.

Notez qu’en python tout nombre non nul est interprété comme True, i.e. if(n), où n est un nombre, seratoujours vrai sauf si n est égal à zéro.

L’opérateur not(x) renvoie la négation (au sens booléen, vrai/faux) d’une expression :>>> not(26)

7

Page 8: Programmation Scientifique avec Python

False>>> not(0)True

and et or permettent de réaliser les opérations logiques usuelles (attention il ne s’agit pas d’opérationsbit à bit, il ne faut donc utiliser and et or que pour des tests booléens vrai/faux) :

>>> 1 and 00>>> 1 and 11>>> 1 or 01

3.4.2 L’instruction if...elif..else

On peut éxécuter une instruction conditonnelle avec if :>>> x=1>>> if x==2 : # est-ce que x est égal à 2?... print "x est égal à 2" # notez les espaces en début de ligne (indentation)... elif x==3 :... print "x est égal à 3"... else :... print "x n’est pas égal à 2"... print "ni à 3"...x n’est pas égal à 2ni à 3

Les espaces en début de ligne (indentation) jouent un rôle important : tant que l’espace reste le mêmeen début de ligne, on reste dans le même “niveau” d’éxécution, de même que dans d’autres langages onutilise des accolades {} pour délimiter les instructions à réaliser. On peut ainsi réaliser des instructionsimbriquées en augmentant le niveau d’indentation :

>>> x=12>>> if (x%2)==0 : # est-ce que x modulo 2 est égal à 0?... if (x%3)==0 :... if (x%7)==0 :... print "x est multiple de 2,3 et 7!"... else :... print "x est multiple de 2 et 3, mais pas de 7..."... else :... print "x est multiple de 2 mais pas de 3"...else :... print "x n’est pas multiple de 2"...x est multiple de 2 et 3, mais pas de 7...

3.4.3 La boucle while

On peut réaliser une série d’instructions tant qu’une condition est réalisée :>>> x=7>>> while x>=1 :... print x,">=1! On continue..."... x = x-1 # on pourrait aussi écrire x -= 17 >=1! On continue...

8

Page 9: Programmation Scientifique avec Python

6 >=1! On continue...5 >=1! On continue...4 >=1! On continue...3 >=1! On continue...2 >=1! On continue...1 >=1! On continue...

3.4.4 Les boucles for

Une boucle for s’écrit de la manière suivante :>>> for i in [2,3,7] : # De manière générale : for variable in liste :... print i...237

Comme il est fastidieux d’écrire un grand nombre de valeurs, on peut utiliser la fonction range() quirenvoie une liste d’entiers :

>>> range(5) # renvoie une liste de 5 entier en partant de 0[0, 1, 2, 3, 4]>>> range(2,5) # renvoie une liste d’entiers, de 2 à 5 (exclu)[2, 3, 4]>>> for i in range(2,5) :... print i...234

Note : la fonction range() crée une liste de nombres qui va servir pour l’itération ; on peut s’en servirpour créer une liste sans que cela soit pour une boucle. Pour une boucle, il vaut en fait mieux utiliser lafonction xrange(), qui ne crée pas une ’vraie’ liste en mémoire mais seulement un itérateur sur une listed’entiers qui permettra à la boucle de se réaliser.

3.4.5 Exercice : décomposition en facteurs premiers

Ecrire une boucle qui, à partir d’un entier n, dresse la liste de ses facteurs premiers en les faisantdéfiler à l’écran. Optionnellement, les stocker dans une liste. Les opérateurs mathématique standardssont * (multiplication), / (division), % (modulo), et les opérateurs de comparaison sont : == , < , <= , > ,>= .

Note : contrairement au C et au C++, l’opération x%n renvoie bien une valeur dans l’intervalle [0 ;n-1],même si le nombre x est négatif...

3.5 FonctionsIl est possible d’utiliser des fonctions en Python. Nous avons déjà utilisé print() et type(). De

manière générale, une fonction s’utilise de la manière suivante : NomDeLaFonction(paramètres)ou (si la fonction renvoie une valeur) : VariableRenvoyée=NomDeLaFonction(paramètres)

Pour définir une nouvelle fonction, il faut utiliser le mot-clef “def” :>>> def MaFonction(nom,age) :... print nom,"a",age,"ans" #noter les espaces en début de ligne...

9

Page 10: Programmation Scientifique avec Python

>>> MaFonction("Obélix",5)Obélix a 5 ans

nom et age sont les paramètres de la fonction ; là encore il n’est pas nécessaire de déclarer le type deces paramètres. En fait on peut très bien utiliser une chaine de caractère pour age :

>>> MaFonction("Obélix","cinq")Obélix a cinq ans

Par contre si la déclaration de la fonction n’impose pas un contrôle sur les types de paramètres, il fautnéanmoins qu’ils soient compatibles pour l’éxécution. Essayer :

>>> def Addition(a,b) :... return a+b # Renvoie une valeur avec “return”...>>> print Addition(1,2) #deux entiers3>>> print Addition(1,3.0) #un entier plus un flottant= un flottant4.0>>> print Addition(1,"toto") # entier+chaîne de caractères = erreur!Traceback (most recent call last) :

File "<stdin>", line 1, in?File "<stdin>", line 2, in Addition

TypeError : unsupported operand type(s) for + : ’int’ and ’str’>>> print Addition("tata","toto") # deux chaînes de caractèrestatatoto

Note : comme pour les boucles c’est l’indentation (le nombre d’espaces en début de ligne) qui définitquelles sont les instructions qui font partie de la fonction. Cela remplace l’utilisation d’accolades {} dansd’autres langages.

Exercice : réutiliser le code écrit pour la décomposition en facteur premiers, et écrire une fonctionqui prend comme argument un nombre entier, et renvoie une liste des facteurs premiers de cet entier.

3.6 Portée des objets : variables locales et globalesComme dans d’autres langages il existe en Python des variables globales et des variables locales. Ces

dernières n’existent qu’au niveau où elles ont été définies. Par défaut, toutes les variables sont locales.Exemple :

>>> x=12.3 # Première variable “x”>>> def fonction1() :... x=1 # Deuxième variable “x”... print x...>>> def fonction2() :... x="Toto" # Troisième variable “x”... print x...>>> print x12.3>>> fonction1()1>>> fonction2()Toto

10

Page 11: Programmation Scientifique avec Python

Dans l’exemple ci-dessus, les 3 variables ont le même nom mais sont complètement indépendantes. Ilest à noter qu’un niveau d’indentation ne peut pas modifier les variables du niveau au-dessus (contraire-ment à ce qui se passe en C/C++). Essayer par exemple :

>>> compte=0>>> def compteur() :... compte+=1... return compte...>>> compteur()Traceback (most recent call last) :

File "<stdin>", line 1, in?File "<stdin>", line 2, in compteur

UnboundLocalError : local variable ’compte’ referenced before assignment

Par contre, il aurait parfaitement été possible de lire la variable compte, sans la modifier.

Pour pouvoir utiliser une variable à différents endoits (autrement qu’en la passant comme paramètre àune fonction), il faut utiliser le mot-clef global :

>>> compte=0>>> def compteur() :... global compte... compte+=1... return compte...>>> compteur()1

Note : en général, il vaut mieux éviter d’utiliser des variables globales, en passant des variables parparamètre aux fonctions.

3.7 ExerciceEcrire une fonction qui prend comme argument deux listes représentant des positions atomiques dans

l’espace (e.g. [”C1”, 0, 0.5 , 0.7]), et qui renvoie leur distance interatomique avec une ligne du type :“La distance entre l’atome C1 et l’atome H3 est de 3.5 A”Pour calculer une racine carrée importer le module de math avec “from math import *”, et utili-

ser “help(math)” pour avoir la liste des fonctions disponibles.

Remarque : pour importer un module (tel que math), il y a deux manières de le faire, avec (a) “importmath” ou (b) “from math import *”. Dans le cas (a), les fonctions du module math s’utiliseront enles faisant précéder de “math.” (exemple : “math.sin(math.pi/3.0)”). Dans le cas (b), il n’estpas nécessaire d’utiliser le préfixe, i.e. python comprendra directement “sin(pi/3.0)”. A priori, lapremière notation n’est à utiliser que si il y a un risque de conflit de noms entre fonctions, si par exemplevous souhaitez redéfinir la fonction sin()...

4 Classes et Objets

4.1 PrésentationHistoriquement se sont succédées plusieurs manières de programmer :

11

Page 12: Programmation Scientifique avec Python

Dans l’approche procédurale, un seul programme exécute séquentiellement une suite d’instructions.Ce fonctionnement convenait bien à des programmes courts, écrits par une seule personne .

Avec des programmes plus longs (et l’intervention de plusieurs personnes, en parallèle ou se suivantdans le temps), il est devenu nécessaire de séparer les différentes tâches du programme avec plusieurs fonc-tions : c’est l’approche structurée.

L’approche la plus moderne est la Programmation Orientée Objet (POO) : les données traitées dans leprogramme sont stockée dans des “objets”, qui comprennent à la fois les données ainsi que des fonctionsqui servent à utiliser l’objet. Par exemple un objet Molécule pourra contenir une liste d’atome, leurs po-sitions, mais également des fonctions pour calculer l’énergie, la charge totale, le moment dipolaire, ... dela molécule. En outre on peut créer des hiérarchies d’objets, qui “héritent” des propriétés de leur ancêtres,etc...

Attention : bien que la programmation Objet soit la plus moderne des approches, les deux autres restentparfaitement valables, en particulier pour de petits projets. Rien ne sert de créer des objets pour des calculsne prenant que quelques lignes ! ! !

4.2 ExempleConstruisons par exemple une classe d’objets de type “polygone” :>>> class Polygone : # Déclaration de la classe... circ=1.0 # Un attribut de la classe, pour stocker

la circonférence... def Circonference(self) : # fonction renvoyant la valeur de la

circonférence... return self.circ...>>> a=Polygone() # Création d’un objet de type Polygone>>> print a.circ # Que vaut sa circonférence (accès direct)?1.0>>> print a.Circonference() # Que vaut sa circonférence (par la

fonction)?1.0>>> a.circ=12.3 # Modification de la circonférence>>> print a.Circonference() # Vérification de la modification12.3

Dans la déclaration ci-dessus, on voit aparaître le mot-clef “self” : c’est ce qui désigne, dans lecorps de la classe, l’objet lui-même. Par exemple, “self.circ” veut dire “la variable circ dans l’objetPolygone où le code est exécuté” (si on est dans le Polygone “a”, cela sera a.circ).

4.3 AttributsUn attribut est une variable (ou donnée) membre stockée dans un objet, comme la variable “circ”

ci-dessus. Il peut y en avoir autant que l’on veut. Il est même possible (contrairement au C++) d’ajouterdes attributs après avoir déclaré une classe : à la suite du code ci-dessus, essayer :

>>> Polygone.surface=45.6 # Ajout de la variable membre ’surface’>>> b=Polygone()>>> print b.circ,b.surface,a.circ,a.surface1.0 45.6 12.3 45.6

L’attribut ajouté est accessible dans tous les objets Polygone, même “a” qui a été créé avant.

12

Page 13: Programmation Scientifique avec Python

4.4 Fonctions membresUne fonction membre est une fonction qui est définie dans la déclaration de la classe, et a accès aux

attributs de la classe, comme la fonction Circonférence(self) définie dans l’objet Polygone. Elleprend au moins un argument, “self”, qui désigne l’objet lui-même (c’est l’équivalent du pointeur thisen C++) et permet à la fonction d’accéder aux attributs. Là encore, on peut utiliser autant de fonctionsmembre que nécessaire.

Il est en général recommandé (en POO) de ne pas accéder directement aux attributs de l’extérieur de laclasse, mais plutôt d’utiliser des fonctions membre pour accéder à ces attributs. L’idée est que la manièredont sont stockées les données peut varier d’une classe à l’autre, alors que les fonctions membres resterontles mêmes.

Par exemple dans la classe Polygone, la circonférence est stockée sous la forme d’un attribut circ,mais dans la classe Carre (voir plus loin), il n’y a pas d’attribut circ, puisque la circonférence peut êtrecalculée direcement à partir du coté... Par contre les deux classes ont la même fonction Circonference(),mais qui procèdent de deux manières différentes pour renvoyer le résultat.

Dans une fonction membre, il est très important de distinguer les variables membre (celles précédéesde “self.”) des variables locales. Les variables membres sont les seules qui ne sont pas détruitesà la fin de l’éxécution d’une fonction membre et qui permettent de ’stocker’ des informations dansl’objet, et donc de les passer de fonction en fonction.

>>> class Objet :... var1=1.0 # variable membre déclarée à la base de la classe... def __init__(self) : # Constructeur... varlocale=1.0 # Variable locale... self.var1=2.4 # Changement de la valeur de la variable membre

self.var1... self.var2="toto" # Ajout d’une seconde variable membre self.var2... def Fonction1(self) :... print self.var1,self.var2... varlocale="tata" # Cette variable est locale et n’a donc rien

à voir avec celle...>>> a=Objet()>>> a.var12.3999999999999999>>> a.var2’toto’>>> a.Fonction1()2.4 toto>>> a.varlocale # erreur car varlocale n’est pas une variable membreTraceback (most recent call last) :File "<stdin>", line 1, in?

AttributeError : Objet instance has no attribute ’varlocale’

Pour chaque objet, il faut avoir le réflexe “self .nomVariable”, de manière à systématiquement dis-tinguer les variables membre des variables locales.

4.5 Fonctions membres spéciales [Facultatif]Certaines fonctions membre sont prédéfinies dans python car elles permettent d’effectuer des opérations

prédéfinies.

13

Page 14: Programmation Scientifique avec Python

4.5.1 Constructeur __init__

Un constructeur est une fonction membre d’un type spécial, qui sert à initialiser un nouvel objet, engénéral en utilisant des arguments :

>>> class Polygone :... circ=1.0... def __init__(self,circ0) : # Prend comme argument la circonférence

initiale... self.circ=circ0 # Initialise la circonférence... def Circonference(self) :... return self.circ...>>> a=Polygone(10.5) # Crée un polygone de circonférence

10.5>>> print a.Circonference()10.5

4.5.2 Destructeur __del__

Le destructeur est la fonction qui est appelée lors de la destruction de l’objet. Il ne prend qu’un argument(self). Il peut servir à ’nettoyer’ des données créées par l’objet.

4.5.3 Opérateurs __add__, __sub__, __mul__, __div__, __pow__

Ce sont les opérateurs (+, -, *, /, **) qui permettent des opérations arithmétiques. Ils prennent deuxarguments, self et un argument désignat le second membre de l’opération :

>>> class Polygone :... circ=1.0... def __add__(self,poly) : # addition... somme=Polygone() # objet à renvoyer... somme.circ=self.circ+poly.circ... return somme...>>> a=Polygone()>>> b=Polygone()>>> b.circ=3.5>>> print (a+b).circ # Circonférence de la somme de a et b4.5

Redéfinir ces opérateurs standard peut être intéressant, mais il ne faut jamais le faire en modifiant la si-gnification originale de l’opérateur (par exemple en calculant une différence en ré-écrivant une fonction__add__).

4.6 Héritage [Facultatif]L’héritage permet de créer des classes qui héritent tout ou partie des propriétés de la ou les classes

parentes. On peut ainsi dériver une classe rectangle de la classe Polygone :>>> class Polygone :... def __init__(self,circ0=2.1) : # On utilise ici un argument

par défaut... self.circ=circ0... def Circonference(self) :... return self.circ...

14

Page 15: Programmation Scientifique avec Python

>>> class Rectangle(Polygone) : # Hérite de la classe Polygone

... def __init__(self,x0=2.5,y0=3.5) :

... self.x=x0

... self.y=y0

... self.circ=2.0*(x0+y0)

...>>> a=Rectangle(3.0,4.0)>>> print a.Circonference() # La fonction Circonference() est héritée

de Polygone14.0

Il est possible de dériver une autre classe, et également de remplacer la fonction Circonference() de laclasse de base par une nouvelle fonction :

>>> class Carre(Rectangle) : # Hérite de la classe Rectangle... def __init__(self,x0) :... self.x=x0... def Circonference(self) : # On réécrit la fonction Circonference()... return 4*self.x...>>> a=Carre(4.0) # Carré de coté 4.0>>> print a.Circonference()16.0

L’héritage peut être très utile lorsque l’on génère de multiples classes ayant des propriétés similaires.Par contre il ne faut pas en abuser, cela peut amener à une programmation inutilement complexe ! Ce n’esten général utile que pour des projets de taille suffisament grande (> 1000 lignes), mais cela peut être aussiutile pour ré-utiliser du code (provenant par exemple d’une librairie développée par quelqu’un d’autre), enajoutant quelques fonctions à une classe pré-existante.

4.7 Attention : opérateur “==”, différence entre égalité et identité, copie et réfé-rence... [Facultatif]

Utilisons les classes définies précédemment, et essayons de comparer des objets :>>> a=Carre(4.0)>>> b=Carre(4.0)>>> c=a>>> print a==b, a==c, b==cFalse True False

Que s’est-il passé ? Clairement les trois carrés sont égaux et on s’attendrait à lire True True Truecomme réponse... En fait l’opérateur == n’a pas comparé les valeurs (est-ce que les carrés sont égaux),mais les adresses, pour tester l’identité des carrés. Ce qui se comprend mieux si on teste le code suivant :

>>> print a.x,c.x4.0 4.0>>> c.x=5.7>>> print a.x,c.x5.7 5.7

Ce qui se passe donc lorsqu’on écrit “c=a” n’est pas la création d’un nouveau carré distinct de a,mais un carré dont l’attribut “x” pointe vers la même case mémoire que celle de a... Ce qui fait que c et areprésentent rigoureusement le même objet.

15

Page 16: Programmation Scientifique avec Python

L’idée derrière ce comportement qui peut souvent induire en erreur est de minimiser l’espace mémoireen faisant par défaut un passage par référence (i.e. en pointant la nouvelle variable vers la même case quela variable originelle) plutôt qu’une copie.

Afin d’éviter cela, il est possible d’effectuer une véritable copie avec la fonction copy.copy() oucopy.deepcopy() :

>>> import copy>>> a=Carre(4.0)>>> b=Carre(4.0)>>> c=copy.copy(a) # en fait il vaut mieux utiliser c=copy.deepcopy(a)>>> print a==b, a==c, b==cFalse False False

4.8 ExerciceCréer une classe Atome qui a 4 attributs : le nom, et les 3 coordonnées x,y,z, avec des fonctions per-

mettant de créer la classe, et d’accéder aux 4 attributs (Nom(), X(), Y() Z()).Créer une fonction calculant la distance entre deux atomes.Ensuite créer une classe Molécule, qui a comme attribut une liste d’atomes, et qui a des fonctions

membre permettant de :– Ajouter un atome– Accéder à un des atomes– Afficher la liste de toutes les distances interatomiques dans la molécule.

5 Lecture et écriture de fichiersOn crée un objet fichier Python avec la fonction open() :>>> MonFichier = open(“NomDuFichier”,’r’)

Le mode peut être ’r’ (read, en lecture seule), ’w’ (en écriture seule)... D’autres modes (mixte lex-ture/écriture, etc...) existent.

La lecture des fichiers texte (i.e. non binaires) se fait avec les fonctions read(), readline() et readlines() :>>> MonFichier.read() # Lit la totalité du fichier sous forme d’un

chaîne de caractères>>> MonFichier.readline() # Lit la ligne suivante du fichier, sous

forme d’une chaîne de caractères>>> MonFichier.readlines() # Lit toutes les lignes du fichier sous

forme d’une liste de chaînes de caractères

Pour lire une liste de nombres contenu dans une ligne, il suffit de lire cette ligne avec la fonction read-line(), puis de séparer les nombres avec la fonction split(). Par exemple :

>>> f=open("tmp0",’r’)>>> ligne=f.readline() # lecture d’une ligne>>> print ligne # Ecriture de la ligne sous forme d’une chaîne

de caractèresToto 1.8 9.2>>> print ligne.split() # On sépare les éléments -> liste[’Toto’, ’0.2’, ’9.2’]>>> print float(ligne.split()[1]) # Conversion en nombre réel0.2>>> f.close() # referme le fichier

help(file) permet de lister l’aide sur l’utilisation des fichiers.

16

Page 17: Programmation Scientifique avec Python

5.1 ExerciceCréez un fichier avec une liste d’atomes (un nom et 3 coordonnées par ligne). Rajoutez une fonction

LireFichier(self, NomFichier) dans votre classe Molecule, qui lit la liste des atomes. Et ensuite listez toutesles distances interatomiques...

Ensuite, ajouter une fonction qui peut écrire dans un fichier la liste des atomes... et vérifiez que vousarrivez à la reliure ensuite !

6 Utilisation de “modules” (standards et librairies extérieures)Pour importer un module, il faut utiliser la commande “import NomDuModule”. Il est alors possible

d’obtenir une aide sur le module avec la commande “help(NomDuModule)”. Les fonctions s’utilisentsous la forme “NomDuModule.NomDeLaFonction(paramètres)”.

Il est également possible d’importer le contenu du module sous la forme “from NomDuModuleimport *” et alors les fonctions peuvent être utilisées directement par “NomDeLaFonction(paramètres)”.

6.1 Modules de calcul scientifique6.1.1 math

Ce module standard comporte toutes les fonctions mathématiques usuelles :>>> import math>>> print math.sin(math.pi/4)0.707106781187>>> print math.log(10.0)2.30258509299

ou :>>> from math import *>>> print sin(pi/4)0.707106781187>>> print log(10.0)2.30258509299

Pour utiliser des fonctions mathématiques sur des complexes, il faudra importer le module cmath enplus du module math.

6.1.2 Scipy

Ce module ne fait pas partie par défaut de Python mais est en général présent, ou peut être obtenu àpartir de l’adresse http ://www.scipy.org.

Ce module permet en particulier d’effectuer des calculs sur des tableaux :>>> from scipy import *>>> a=zeros([2,5],floating) # un tableau de 2 lignes et 5 colonnes>>> print a # rempli de 0.0 (nombres réels)[[ 0. 0. 0. 0. 0.][ 0. 0. 0. 0. 0.]]>>> a[1,3]=4.0 # Modification d’un élément>>> print a[[ 0. 0. 0. 0. 0.][ 0. 0. 0. 4. 0.]]>>> a[0, :]=1.0 # Modification de la première ligne>>> print a[[ 1. 1. 1. 1. 1.]

17

Page 18: Programmation Scientifique avec Python

[ 0. 0. 0. 4. 0.]]>>> print a[ :,3] # Affichage de la quatrième colonne[ 1. 4.]>>> sin(a)array([[ 0.84147098, 0.84147098, 0.84147098, 0.84147098, 0.84147098],[ 0. , 0. , 0. , -0.7568025 , 0. ]])

Attention sur la dernière ligne on utilise une fonction sin(), qui provient du module scipy. Si les deuxmodules (math et scipy) étaient importés avec “from NomDuModule import *”, il y aurait uneambiguité sur quelle fonction sin() à utiliser... En fait la dernière fonction sin() importée écraserait laprécédente...

Dans ces cas là, n’utiliser que “import NomDuModule” et ensuite math.sin() et scipy.sin()suivant la fonction désirée. On peut même n’importer qu’une fonction d’un module, par exemple avec“from math import sin”.Lire l’aide de scipy pour voir les différentes fonctions disponibles. En particulier, on peut créer des tableauxavec les fonctions ones, zeros , et en utilisant comme type : complex64, complex128, float32, float64,int16, int32, int64, suivant le type de donnée et la précision souhaitée.

6.1.3 Sous-modules de scipy

Scipy est un ensemble qui comprend de nombreux modules utiles pour des scientifiques :* cluster : information theory functions (currently, vq and kmeans)* weave : compilation of numeric expressions to C++ for fast execution* fftpack : fast Fourier transform module based on fftpack and fftw when available* ga : genetic algorithms* io : reading and writing numeric arrays, MATLAB .mat, and Matrix Market .mtx files* integrate : numeric integration for bounded and unbounded ranges. ODE solvers.* interpolate : interpolation of values from a sample data set.* optimize : constrained and unconstrained optimization methods and root-finding algorithms* signal : signal processing (1-D and 2-D filtering, filter design, LTI systems, etc.)* special : special function types (bessel, gamma, airy, etc.)* stats : statistical functions (stdev, var, mean, etc.)* linalg : linear algebra and BLAS routines based on the ATLAS implementation of LAPACK* sparse : Some sparse matrix support. LU factorization and solving Sparse linear systems.

Là encore, de la documentation est disponible (après import du module) avec la commande “help(NomDuModule)”Par exemple le module FFTPACK :

>>> import scipy>>> from scipy import fftpack>>> a=scipy.array(range(20),scipy.floating)>>> print a[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.15. 16. 17. 18. 19.]>>> print scipy.fftpack.fft(a)[ 190. +0.j -10.+63.13751515j -10.+30.77683537j-10.+19.62610506j -10.+13.7638192j -10.+10.j-10. +7.26542528j -10. +5.09525449j -10. +3.24919696j-10. +1.5838444j -10. +0.j -10. -1.5838444j-10. -3.24919696j -10. -5.09525449j -10. -7.26542528j-10.-10.j -10.-13.7638192j -10.-19.62610506j-10.-30.77683537j -10.-63.13751515j]

18

Page 19: Programmation Scientifique avec Python

6.1.4 MatPlotlib/PyLab (http ://matplotlib.sf.net)

Matplotlib est un module dédié aux représentations graphiques de données scientifiques, calqué surle modèle de MatLab - en fait les commandes du module pylab sont écrites pour être compatibles avecMatLab. Pour utiliser PyLab de manière interactive (i.e. en pouvant taper des commandes tout en ayant lafenêtre graphique affichées), il faut utiliser ipython avec l’option pylab, i.e. : ipython -pylab. Il est ànoter que dans ce mode, les fonctions d’utilisation des tableaux de scipy sont automatiquement importés.Exemple :

[vincent@GRE018468 ~]$ ipython -pylabPython 2.4.3 (#2, Oct 6 2006, 15 :32 :41)Type "copyright", "credits" or "license" for more information.IPython 0.7.2 -- An enhanced Interactive Python.? -> Introduction to IPython’s features.%magic -> Information about IPython’s ’magic’ % functions.help -> Python’s own help system.object? -> Details about ’object’.?object also works,?? prints more.

Welcome to pylab, a matplotlib-based Python environment. For more information,type ’help(pylab)’.

In [1] : x=linspace(-6,6,101) # Tableau de -1 à 1 inclus avec 101éléments

In [2] : y=linspace(-6,6,101)[ :,newaxis] # idem mais on ajoute unedimension au tableau

In [3] : plot(x,sin(x))Out[3] : [<matplotlib.lines.Line2D instance at 0xb7990fec>]In [4] : imshow(x**2+y**2) # Affiche la fonction 2D x^2+y^2Out[4] : <matplotlib.image.AxesImage instance at 0xb2a78e0c>In [5] : jet() # on change la table de couleursIn [6] : colorbar() # on change la table de couleursOut[6] : <matplotlib.colorbar.Colorbar instance at 0xb2a82d4c>

6.1.5 Autres modules scientifiques

PyMol et cctbx : pour la cristallographie (en particulier des protéines)PyQuante : Chimie QuantiqueSnack : pour le traitement du signalpyVTK et Mayavi, OpenDX : pour la représentation graphique en 3D

etc... Une majeure partie des librairies de calcul développées en fortran ou en C/C++ sont ainsi dispo-nibles en Python (voir plus bas comment créer une interface avec python grâce à Boost.Python ou SWIG)

Une liste (très incomplète) de modules disponibles pour Python est disponible sur le site web consacréau language (http ://www.python.org/pypi ; http ://www.python.org/moin/NumericAndScientific). De nom-breux modules peuvent également se trouver à partir du site Sourceforge (en cherchant dans les projetsutilisant python comme langage : http ://sourceforge.net/softwaremap/trove_list.php ?form_cat=178).

Mais le meilleur moyen de savoir si un outil particulier a été développé en Python est encore d’utiliserGoogle !

De nombreux laboratoires utilisent et développent des outils à base de Python pour le calcul scienti-fique, à Grenoble (ILL, ESRF, CEA, CNRS) et ailleurs (en particulier le Laboratoire Lawrence LivermoreLLNL, le CERN).

19

Page 20: Programmation Scientifique avec Python

7 Performance et interface C/C++ <-> Python [Facultatif]

7.1 Performance : C/C++ vs PythonEtant un langage interprété, Python présente des perfomances en terme de calcul assez médiocres si on

ne prend pas garde à la méthode utilisée. Par exemple pour une simple opération d’addition de 2 tableauxde 100 000 éléments, on peut calculer le nombre d’opérations par seconde :

# -*- coding : iso-8859-15 -*-import scipyimport time # Module de fonction sur le temps (date, heure)taille=100000

# 1ère version avec une boucle en Pythonnbiter=10a=range(taille) # Avec une boucleb=range(taille)c=range(taille)t1=time.time() # time.time() renvoie le nombre de secondes écouléesfor i in xrange(nbiter) :

for i in xrange(taille) :c[i]=a[i]+b[i]

t2=time.time()print "Boucle : %6.3f Mflops"%( (taille*nbiter)/(t2-t1)/1e6)

# 2ème version vectorisée à l’aide d’un tableaunbiter=1000a=scipy.ones(taille) # Avec des tableauxb=scipy.ones(taille)c=scipy.ones(taille)t1=time.time()for i in xrange(nbiter) :

c=a+bt2=time.time()print "Tableau : %6.3f Mflops"%( (taille*nbiter)/(t2-t1)/1e6)

La différence de temps d’éxécution est très nette, plus qu’un facteur 50 ! Si on compare avec un programmeen c++ (compiler en utilisant “g++ vite.cpp -o vite” et éxécuter le programme vite avec “./vite”) :

# 3ème version en c++#include <stdlib.h>#include <time.h>#include <iostream>using namespace std;int main(){

const unsigned long taille=100000;const unsigned long nbiter=1000;long *a=new long[taille];long *b=new long[taille];long *c=new long[taille];clock_t time0=clock();for(unsigned long i=0;i<nbiter;i++){

20

Page 21: Programmation Scientifique avec Python

long *pa=a;long *pb=b;long *pc=c;for(unsigned long j=0;j<taille;j++)

*pc++ = *pa++ + *pb++;}clock_t time1=clock();const float seconds=(float)(time1-time0)/(float)CLOCKS_PER_SEC;cout <<"C++ : "<< (float)taille * (float)nbiter/ seconds /1e6<<endl;delete[]a;delete[]b;delete[]c;

}

La différence reste importante avec Python (facteur 2 par rapport au calcul vectorisé), mais sans êtretrop gênante pour des calculs pas trop longs (<1h).

7.1.1 Utilisation de scipy.weave

Pour une petite partie de calcul qui doit être exécutée très rapidement, il est possible d’insérer du codeC++ à l’intérieur d’un programme Python - cette partie du code est alors compilée automatiquement, estpeut accélérer considérablement certaines opérations. Pour cela il faut importer scipy et le sous-modulescipy.weave - pour insérer du code de type C++ il faut alors utiliser la fonction scipy.weave.inline.L’exemple ci-dessus devient alors :

# -*- coding : iso-8859-15 -*-import scipyfrom scipy import weaveimport scipynbiter=1000a=scipy.ones(taille)b=scipy.ones(taille)c=scipy.ones(taille)def testweave() :

code="""for(unsigned int ct=0;ct<nbiter;++ct){

const double *pa=a.data();const double *pb=b.data();double *pc=c.data();for(unsigned int i=0;i<taille;++i) *pc++ = *pa++ + *pb++;

}"""

err = weave.inline(code,[’a’, ’b’, ’c’, ’taille’, ’nbiter’],type_converters=weave.converters.blitz,compiler = ’gcc’)

testweave() # Le premier appel est long, car le code est alors compilé!nbiter=1000t1=time.time()testweave() # On recommence, en utilisant les code pré-compilét2=time.time()print "SciPy.weave : %6.3f Mflops"%( (taille*nbiter)/(t2-t1)/1e6)

21

Page 22: Programmation Scientifique avec Python

7.2 Interface C/C++ <-> Python avec SWIGLorsque des calculs longs (soit intrinsèquement, soit parce qu’il sont répétés) sont nécessaires, il vaut

mieux sous-traiter les calculs à un langage plus performant (en pratique C++ ou fortran), tout en organisantle programme (entrées/sorties, représentation des données, interface utilisateur etc...) en Python.

Lorsqu’aucune librairie proposant ce calcul n’est disponible sous Python (cela devient de plus en plusrare ! Un outil essentiel du programmateur scientifique est aujourd’hui Google !), il peut être nécessairede créer cette interface (et éventuellement le programme en C+C++/fortran). Il existe pour cela des pro-grammes spécialisés, les plus utiles aujourd’hui étant Boost.Python (http ://www.boost.org/libs/python/doc/index.html)et SWIG (http ://www.swig.org/ ). Nous allons présenter (très) rapidement ce dernier.

Séparer le petit programme en C++ ci-dessus en 2 fichiers :– le fichier d’en-tête test1.h qui ne comprend qu’une seule ligne de déclaration “void FonctionTest(longtaille,long nbiter);”

– le ficher de code test1.cpp qui contient le même code que la fonction ci-dessus, en remplaçantla fonction main() par une fonction FonctionTest() prenant comme argument le nombre d’élé-ments et le nombre d’itérations à effectuer.

Ensuite créer un fichier d’interface “test1.i” qui définira les éléments à partager entre SWIG et Python :%module test1%{#include "test1.h"%}extern void FonctionTest(long,long);

Enfin, compiler et créer l’inteface avec SWIG avec :swig -python -module test1.i # crée test1_wrap.cg++ -c test1_wrap.cxx test1.cpp -I /usr/include/python2.3/g++ -shared test1_wrap.o test1.o -o _test1.so # crée _test1.soEnsuite il n’y a plus qu’à tester dans l’interpréteur Python :>>> import test1>>> help(test1)>>> test1.FonctionTest(100000,100)C++ : 4.54545e+07

Bien sûr ce travail d’interface peut être complexe, donc le réserver aux calculs réellements intenses. Rienne sert de passer plus de temps à écrire un programme que vous n’en passerez à l’utiliser !

22