Formation Python Traitement et visualisation de données scientifiques Jour 2 – Prog. Orientée Objet Fernando NIÑO Legos/IRD Janvier 22-30 2009 Rappel • • Littéraux Structures de données – Séquences (listes) – Dictionnaires – Tuples • Blocs : indentation et symbole ‘:’ for i in liste: suite while i < 3: • Python = réutilisation – Bibliothèque standard – Modules externes python setup.py install --home=~ 2 © 2009 Fernando NIÑO Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 3 © 2009 Fernando NIÑO Programmation Orientée Objet • Encapsulation – Structure de données va ensemble avec ses procédures de traitement liste.append(element) • Héritage – Eviter la duplication de code fichier fichierZip fichierTexte • Surcharge – Un même nom pour différentes fonctions (distinguées par contexte - ou signature) mafonction(a,b,c) / mafonction(a) ça n’existe pas en Python ! Un seul nom admis ! 4 © 2009 Fernando NIÑO Programmation Orientée Objet • Polymorphisme – Le même nom de fonction pour différents arguments len(‘chaine’) len([1,2,3]) – Permet de créer des algorithmes génériques listefig=[Carre(2),Cercle(1)] ... surfaceTotale=0. for fig in listefig: surfaceTotale += fig.surface() 5 © 2009 Fernando NIÑO Encapsulation • L’idée est de regrouper un état (données) et un comportement (code) dans une classe. class MaClasse: Nom habituel: REVEILLE=1 ENDORMI=0 def __init__(self,etatinitial): self.etat = etatinitial def reveil(self): self.etat = self.REVEILLE print 'Driiiiing ' def dort(self): self.etat = MaClasse.ENDORMI print 'Zzzzzz ' 6 © 2009 Fernando NIÑO Encapsulation • L’idée est de regrouper un état (données) et un comportement (code) dans une classe. class MaClasse: REVEILLE=1 ENDORMI=0 def __init__(self,etatinitial): self.etat = etatinitial def reveil(self): self.etat = self.REVEILLE print 'Driiiiing ' def dort(self): self.etat = MaClasse.ENDORMI print 'Zzzzzz ' 6 © 2009 Fernando NIÑO Encapsulation • L’idée est de regrouper un état (données) et un comportement (code) dans une classe. class MaClasse: REVEILLE=1 Variables ENDORMI=0 def __init__(self,etatinitial): self.etat = etatinitial def reveil(self): self.etat = self.REVEILLE print 'Driiiiing ' def dort(self): self.etat = MaClasse.ENDORMI print 'Zzzzzz ' de classe 6 © 2009 Fernando NIÑO Utilisation de Classes moi=MaClasse(MaClasse.ENDORMI) toi=MaClasse(MaClasse.ENDORMI) >>> moi.reveil <bound method MaClasse.reveil of <__main__.MaClasse instance at 0x58918>> >>> moi.reveil() MaClasse Driiiiing >>> moi.dort() REVEILLE ENDORMI Zzzzzz moi etat toi etat 7 © 2009 Fernando NIÑO Où sont les variables ? class Donnees(object): xc=’xc’ yc=’yc’ def __init__(self): x=None y=None pass d=Donnees() d.x=1 d.y=2 e.x=3 e.y=4 e.xc Donnees xc yc d x y e x y 8 © 2009 Fernando NIÑO Héritage – figure.py class Figure: def __init__(self): pass def surface(self): raise NotImplementedError def message(self): print "je suis une figure" class Carre(Figure): def __init__(self,cote): self.cote=cote def surface(self): return self.cote*self.cote carre=Carre(2.) carre.message() 9 © 2009 Fernando NIÑO Surcharge • • Regarde la signature d’une fonction...en C++ Ne marche PAS en Python (surcharge.py) def surface(quoi,param): if quoi == 'carre': return param*param else: return 3.14159*param*param def surface(quoi,param1,param2): if quoi == 'triangle': return param1*param2/2. else: return param1*param2 • Utilise arguments par défaut, duck typing... 10 © 2009 Fernando NIÑO Surcharge • • Regarde la signature d’une fonction...en C++ Ne marche PAS en Python (surcharge.py) def surface(quoi,param): if quoi == 'carre': return param*param Remplace ! else: return 3.14159*param*param def surface(quoi,param1,param2): if quoi == 'triangle': return param1*param2/2. else: return param1*param2 • Utilise arguments par défaut, duck typing... 10 © 2009 Fernando NIÑO Polymorphisme – polymorphisme.py class Cercle(Figure): def __init__(self,rayon): self.rayon=rayon def surface(self): return 3.14159*self.rayon*self.rayon listefig=[Carre(2),Cercle(1)] surfaceTotale=0. for fig in listefig: surfaceTotale += fig.surface() Par contexte il sait quelle fonction appeler 11 © 2009 Fernando NIÑO Exercice • Modifier polymorphisme.py – en ajoutant la sous-classe Triangle – en ajoutant la sous-sous-classe TriangleIsocele – en ajoutant la méthode perimetre, sauf pour le triangle – testez avec une liste de figures listefig=[Carre(2),Cercle(1), Triangle(2,3),TriangleIsocele(2,3)] 12 © 2009 Fernando NIÑO Solution • Classe de base #class Figure: class Figure(object): def __init__(self): pass def surface(self): raise NotImplementedError def perimetre(self): raise NotImplementedError def message(self): print "je suis une figure" New-style class 13 © 2009 Fernando NIÑO Solution • Classes Cercle et Carre class Carre(Figure): def __init__(self,cote): self.cote=cote def surface(self): return self.cote*self.cote def perimetre(self): return self.cote*4 from math import pi class Cercle(Figure): def __init__(self,rayon): ou self.rayon=rayon def surface(self): return pi*self.rayon*self.rayon def perimetre(self): return 2.*pi*self.rayon import math math.pi © 2009 Fernando NIÑO 14 Solution • Classes triangle class Triangle(Figure): def __init__(self,base,hauteur): self.base=base self.hauteur=hauteur def surface(self): return self.base*self.hauteur/2. class TriangleIsocele(Triangle): pass 15 © 2009 Fernando NIÑO Solution • Test listefig=[Carre(2),Cercle(1),Triangle (2,3),TriangleIsocele(2,3)] surfaceTotale=0. for fig in listefig: surf= fig.surface() surfaceTotale += surf print "Pour une figure de type %s et classe %s la surface est %f" % (type(fig),fig.__class__,surf) print "surfaceTotale = %f " % surfaceTotale depend si c’est new-style ou non assez barbare... 16 © 2009 Fernando NIÑO Applications CTOH • • Chaînes de traitement génériques L’idée: avoir une interface unifiée pour les corrections. • Classe correction abstraite: class Correction(object): """Classe de base pour toutes les corrections CTOH;elle permet de définir les paramètres généraux - constantes - repertoires de travail par défaut - interface obligatoire """ def __init__(self): raise NotImplementedError 17 © 2009 Fernando NIÑO Application CTOH (suite) # suite de Class Correction def apply(self,data): # interface obligatoire raise NotImplementedError @classmethod # methode de classe - utilitaire def readTrace(cls, dateString, satellite, ntrace): pass 18 © 2009 Fernando NIÑO Application (suite) class CorrectionIono(Correction): """Correction ionosphérique""" def __init__(self): self.ionoSource='GIM' class CorrectionIonoGIM(CorrectionIono): def apply(self,data): return 0 class CorrectionIonoScharroo(CorrectionIono): def apply(self,data): return 0.01 19 © 2009 Fernando NIÑO Application (suite) def testNiveauMer(self): ci = CorrectionIonoGIM() corrGIM = ci.apply(self.testTrace) ciSch = CorrectionIonoScharroo() corrSch = ciSch.apply(self.testTrace) cw = CorrectionWetTropoCLS() corrWet = cw.apply(self.testTrace) alt_range=1336E6 slaGIM = alt_range - corrGIM - corrWet slaSch = alt_range - corrSch - corrWet self.assertAlmostEqual(slaGIM, slaSch,1) après la virgule # 1 place 20 © 2009 Fernando NIÑO Tests unitaires: unittest class CorrectionTests(unittest.TestCase): def setUp(self): """Called before each and every test""" self.testTrace = Correction.readTrace('2007/06/23', 'Jason-2',12) def tearDown(self): """Called after each and every test""" pass def testExample(self): """Trivial test""" self.assertEqual(1,1) if __name__ == '__main__': unittest.main() 21 © 2009 Fernando NIÑO Application (correction.py) Si tout est ok... python correction.py ... ---------------------------------------------------------Ran 3 tests in 0.000s OK 22 © 2009 Fernando NIÑO Application (correction.py) • S’il y a un problème ..F =========================================================== FAIL: testNiveauMer (__main__.CorrectionTests) -------------------------------------------------------Traceback (most recent call last): method testNiveauMer in correction.py at line 88 self.assertAlmostEqual(slaGIM, slaSch,1) # 1 place après la virgule AssertionError: 1335999997.0 != 1335999996.9000001 within 1 places --------------------------------------------------------------Ran 3 tests in 0.000s FAILED (failures=1) Program exited. 23 © 2009 Fernando NIÑO Formation Python Python - Le Langage Présentation Travailler avec Python Les bases du langage Structures de données Contrôle du flux d'exécution Gestion des fichiers Le Langage Encapsulation POO Dérivation Réutilisation Gestion des erreurs Exceptions Logger 24 © 2009 Fernando NIÑO Gestion des erreurs • • Les erreurs, ça lance des exceptions: Les exceptions qui ne sont pas traitées, génèrent par défaut un traceback comme ceci: x=1/0 ------------------------------------------------exceptions.ZeroDivisionError Traceback (most recent call last) /Users/nino/FormationPython/<ipython console> ZeroDivisionError: integer division or modulo by zero 25 © 2009 Fernando NIÑO Les clauses try...except...else • Pour attraper les erreurs, il faut les enfermer dans une clause try: x=0. try: Type d’exceptions (sous-classe), plusieurs clauses admises print 1/x except Exception, error: print str(error) else: print 'tout est ok' – ça donne float division 26 © 2009 Fernando NIÑO try...finally • Permet de s’assurer qu’un bloc sera toujours executé file=open(nomfichier,’r’) try: lines=file.readlines() except Warning, error: print str(error) finally: file.close() • La hiérarchie des classes d’exceptions a changé BaseException # New in Python 2.5 |- KeyboardInterrupt |- SystemExit |- Exception |- (all other current built-in exceptions) http://python.org/doc/2.5/lib/module-exceptions.html 27 © 2009 Fernando NIÑO Exceptions, raise - hiérarchie • Avant python 2.5 try: ... except (KeyboardInterrupt, SystemExit): raise # remonte l’exception except: # Log error... # Continue running program... • Après 2.5 try: ... except Exception: # Log error... # Continue running program... 28 © 2009 Fernando NIÑO Modification traceback - logging if __name__ == '__main__': if len(sys.argv) == 1: modetest=None elif len(sys.argv) == 2 and sys.argv[1] == '-t': modetest=True else: print "USAGE: %s [-t]" % sys.argv[0] logger=initLogging(modetest) logger.info(“Deb x=0. try: print 1/x except Exception, error: print_exception(sys.exc_info()) else: print 'tout est ok' 29 © 2009 Fernando NIÑO initLogging (initlogging.py) def initLogging(modetest): logger = logging.getLogger('tracebackEx') if modetest: hdlr = logging.FileHandler('formation.log') else: hdlr = logging.FileHandler('formtest.log') formatter = logging.Formatter('%(asctime)s % (levelname)s %(message)s') hdlr.setFormatter(formatter) logger.addHandler(hdlr) logger.setLevel(logging.INFO) return logger 30 © 2009 Fernando NIÑO Traceback info (tracebackEx.py) • Langage dynamique - en cas d’erreur on connaît tout le contexte: def print_exception(excinfo): import traceback logger.error(excinfo[0]) logger.error(excinfo[1]) logger.error("Traceback: ") tb=excinfo[2] for s in traceback.format_list(traceback.extract_tb(tb)): logger.error(s) 31 © 2009 Fernando NIÑO Utilisation traceback / logger • Logger sait faire beaucoup de choses import logging.handlers #logging.handlers.RotatingFileHandler #logging.handlers.SysLogHandler • Résultat de l’exemple 2006-10-18 14:46:44,189 2006-10-18 14:46:44,189 2006-10-18 14:46:44,189 2006-10-18 14:46:44,190 2006-10-18 14:46:44,190 print 1/x • INFO Debut du script ERROR exceptions.ZeroDivisionError ERROR float division ERROR Traceback: ERROR File "tracebackEx.py", line 38, in ? On peut avoir plusieurs handlers pour un logger 32 © 2009 Fernando NIÑO Formation Python Python - Scientifique Installation Architecture Numpy Arrays Opérations Matplotlib Application CTOH 33 © 2009 Fernando NIÑO Installation numpy & friends • Installer numpy (http://numpy.scipy.org) cd ~/build tar xvfz ~/fnino/distrib/numpy-* cd numpy* python setup.py install --home=~ • Installer scipy – idem, mais nécessite blas-devel et lapack-devel • Installer matplotlib – matplotlib core: zlib, zlib-devel, libpng, libpng-devel, – freetype, freetype-devel, freetype-utils – gtk backend: gtk2-devel, gtk+-devel, pygtk2, glib-devel, – pygtk2-devel, gnome-libs-devel, pygtk2-libglade 34 © 2009 Fernando NIÑO Architecture SciPy: Algorithmes Scientifiques MatPlotLib : Graphiques NumPy : Structures de à la Matlab données Python & Système de base (X11, Gtk....) 35 9 © 2009 Fernando NIÑO Utilisation NumPy • Arrays from numpy import array,arange,sin a = array( [ 10, 20, 30, 40 ] ) b = arange( 4 ) c = a+sin(b) • Arrays multi-dimensionnels from numpy import ones,shape x = ones(3,4) # Erreur de syntaxe attend un tuple x = ones( (3,4) ) x.shape # Variable d’instance 36 © 2009 Fernando NIÑO Opérations n-dimensionnelles • Classique y = x*3 • Plus bizarre x+a x * y • # Ca fait quoi ??? # Ca fait quoi ??? Les tranches, ça marche aussi a[2:4] = -7,-3 x[1,:]=0. 37 © 2009 Fernando NIÑO Reshape • • En interne, les données d’un array sont stockées en contigu, leur interprétation est donnée par le paramètre shape à leur création. Il peut être modifié a = arange(10).reshape(2,5) • array transforme des séquences Pythons en vecteurs 1-dimension, des séquences des séquences en vecteurs 2-dimensions, des séquences des séquences des séquences en vecteurs 3-dimensions.... b = array( [ (1.5,2,3), (4,5,6) ] ) 38 © 2009 Fernando NIÑO Création d’arrays • Outre le constructeur array zeros( (m,n) ) ones ( (m,n), dtype=int16 ) empty ( (m,n) ) # Mémoire non-initialisée arange( debut, fin, pas ) linspace (debut, fin, combien) # pour v.flottante x = linspace( 0, 2*pi, 100 ) f = sin(x) z= floor(10*random.random((3,4))) 39 © 2009 Fernando NIÑO Opérations matricielles • • Par défaut, toutes les opérations se font élément par élément Pour opérations matricielles, il faut l’opérateur explicite: A = array( [[1,1], [0,1]] ) B = array( [[2,0], [3,4]] ) dot(A,B) mat(A)*mat(B) # Conversion aux matrices A et B a=array([1,0,0]) b=array([0,1,0]) cross(a,b) 40 © 2009 Fernando NIÑO Autres opérations • • • • • • • • Array Creation arange, array, copy, empty, empty_like, eye, fromfile, fromfunction, identity, linspace, logspace, mgrid, ogrid, ones, ones_like, r_, zeros, zeros_like Conversions astype, atleast_1d, atleast_2d, atleast_3d, mat Manupulations ..., array_split, column_stack, concatenate, diagonal, dsplit, dstack, flacodeen, hsplit, hstack, item, newaxis, ravel, repeat, reshape, resize, squeeze, swapaxes, take, transpose, vsplit, vstack Questions all, any, nonzero, where Ordering argmax, argmin, argsort, max, min, ptp, searchsorted, sort Operations choose, compress, cumprod, cumsum, inner, fill, imag, prod, put, putmask, real, sum Basic Statistics cov, mean, std, var Basic Linear Algebra cross, dot, outer, svd, vdot 41 © 2009 Fernando NIÑO Exercice: numpy et tests unitaires • Modifier correction.py pour ajouter des tests unitaires avec la classe Matrice: class Matrice(object): def __init__(self,A): self.mat = A def addition(self, B): return Matrice(self.mat + B.mat) def soustraction(self,b): pass class MatriceTests(unittest.testCase): pass © 2009 Fernando NIÑO 42 Exercice (bis) class MatriceTests(unittest.testCase): def testMatrice(): a = Matrice(numpy.zeros((3,3)) b = Matrice(numpy.zeros((3,3)) c = a.addition(b) self.assertEquals(c,numpy.zeros((3,3))) if __name__ == ‘__main__’: unittest.main() 43 © 2009 Fernando NIÑO Transformées de Fourier from numpy import sin, pi, linspace,fft x = linspace(0,2*pi,8) y = sin(x) + sin(4*x) yhat=fft.rfft(y) # partie réelle y2=fft.irfft(yhat) # inverse y2-y 44 © 2009 Fernando NIÑO Exercice • Définir (pas de mise en oeuvre !) une hiérarchie de classes qui réponde à l’utilisation suivante: if __name__ == '__main__': if len(sys.argv) != 2: print "USAGE: %s <nomfichier>|-s" % sys.argv[0] else: if sys.argv[1] == '-s': d=DonneesSynthetiques() print "Generation de données synthétiques" else: d=DonneesFichier(sys.argv[1]) print "Traitement fichier %s " % d.nomfichier dhat=d.transFourier() – Quelles classes ? Quelles variables de classe ? d’instance ? 45 © 2009 Fernando NIÑO Solution • fourier1.py class Donnees(object): def transFourier(self): pass class DonneesFichier(Donnees): def __init__(self,nomfichier): self.nomfichier=nomfichier class DonneesSynthetiques(Donnees): pass 46 © 2009 Fernando NIÑO Exercice • Faites la mise en oeuvre de fourier1 – Pour les données fichier, lisez un fichier texte qui comporte une ligne par donnée, avec pas de temps consant et égal à 1 seconde. L’ensemble définit donc une fonction y(t). – Pour les données synthétiques, créer une gaussienne exp(-x*x) – entre 0 et 2*pi, avec 301 points 47 © 2009 Fernando NIÑO SciPy • Fonctionnalités – – – – – – • • Interpolation Echantillonage Regression Optimisation Filtrage .... Utilise BLAS et LAPACK http://www.scipy.org/Cookbook/Interpolation 48 © 2009 Fernando NIÑO Formation Python Python - Scientifique Numpy Matplotlib Graphisme histogrammes Application CTOH 49 © 2009 Fernando NIÑO Matplotlib • Pylab fournit graphisme à la Matlab from numpy import * import pylab x = linspace(0,2*pi,300) y = sin(x) #+ sin(4*x) yhat=fft.fft(y) yhat2=abs(yhat) # L’amplitude pylab.plot(x, yhat2) pylab.show() • Essentiel – commande plot – commande show – commande figure 50 © 2009 Fernando NIÑO Matplotlib • Concepts – Figure courante : gcf (get current figure) – Axes courants : gca (get current axes) – Toutes les commandes de plot et texte s’appliquent à la figure courante from pylab import * figure(1) plot([1,2,3]) figure(2) plot([4,5,6]) # the first figure figure(1) title('Easy as 1,2,3') show() # figure 1 current # figure 1 title # a second figure – 51 © 2009 Fernando NIÑO Possibilités Matplotlib • http://matplotlib.sourceforge.net/tutorial.html • Très important: à la compilation, matplotlib utilise des backends # > > > > > > the GUI backends python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py -dGTK -dGTKAgg -dGTKCairo -dTkAgg -dWX -dWXAgg # > > > > > > > The image backends, no python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py python subplot_demo.py window pops -dAgg # -dCairo # -dPS # -dSVG # -dGD # -dPaint # -dEMF # # # # # # # GTK GUI with gdk drawing GTK GUI with antigrain geometry rendering GTK GUI with Cairo rendering Tkinter GUI with antigrain rendering WX backend WX GUI with antigrain rendering curri up; you must call savefig antigrain geometry backend image Cairo backend postscript backend SVG backend GD backend Paint backend EMF backend 52 © 2009 Fernando NIÑO Configuration matplotlib • • A l’utilisation il faut lui dire quel backend utiliser. Le plus simple cat ~/.matplotlib/matplotlibrc backend: TkAgg numerix: numpy 53 © 2009 Fernando NIÑO Matplotlib exemple de texte from pylab import * t = arange(0.0, 2.0, 0.01) s = sin(2*pi*t) plot(t,s) title(r'$\alpha_i > \beta_i$', fontsize=20) text(1, -0.6, r'$\sum_{i=0}^\infty x_i$', fontsize=20) text(0.6, 0.6, r'$\cal{A}\rm{sin}(2 \omega t)$', fontsize=20) xlabel('time (s)') ylabel('volts (mV)') savefig('mathtext_tut', dpi=50) show() 54 © 2009 Fernando NIÑO Nombres aléatoires - randomex.py import random histogram = [0] * 20 # calculate histogram for gaussian # noise, using average=5, stddev=1 for i in range(1000): i = int(random.gauss(5, 1) * 2) histogram[i] = histogram[i] + 1 # print the histogram m = max(histogram) for v in histogram: print "*" * (v * 50 / m) 55 © 2009 Fernando NIÑO Exercice - Déjouez le Piège • • • Renommez le fichier randomex.py à random.py Que se passe-t-il à l'exécution ? Pourquoi ? 56 © 2009 Fernando NIÑO Formation Python Python - Scientifique Numpy Matplotlib Graphisme histogrammes Application CTOH 57 © 2009 Fernando NIÑO Données ENVISAT • Voir envisat.py python envisat.py RA2_MWS_2POFP20070302_010120_00003017A056_00045_26151_0145.N1 • Réorganisez-le pour séparer la déclaration de types de la logique (faire de sorte que import envisat_datatypes • soit possible) 58 © 2009 Fernando NIÑO Envisat2.py • • Plus clair.. Utilisation de – numpy.dtype – numpy.recarray • Très bon outils pour la lecture des données binaires: – gèrent le padding – endianness.... • Remarquez que le fichier s’ouvre avec open(nomfichier,’rb’) – r comme ‘read-only’, b comme “binaire” 59 © 2009 Fernando NIÑO Numpy : les types • Voir les types disponibles: numpy.typeDict In [6]: numpy.dtype(numpy.uint32) Out[6]: dtype('uint32') In [7]: numpy.dtype('uint32') Out[7]: dtype('uint32') In [8]: numpy.dtype('u4') Out[8]: dtype('uint32') 60 © 2009 Fernando NIÑO netCDF • Avec ipython from Scientific.IO.NetCDF import NetCDFFile as Dataset nc=Dataset('climap.nc','r') • Avec la ligne de commande sur le dossier examples/ netcdf python ncplotter.py climap.nc < myresponses 61 © 2009 Fernando NIÑO Formation Python Python - Classes et paramètres Variables d'instance Variables de classe Paramètres par défaut Paramètres nommés Deepcopy 62 © 2009 Fernando NIÑO Variables d’instance/classe • Un programme informatique est fait pour traiter des données. En Python où peut-il les stocker ? – Variables globales global MAVARIABLEGLOBAL # Déconseillé – Variables de classe ou d’instance class MaClasse(object): varclasse1=1 # Pratique pour constantes varclasse2=2 def __init__(self): self.varinstance=1 – On peut donc print MaClasse.varclasse1 mc=MaClasse() mc.varclasse2='mc' print MaClasse.varclasse2 print mc.varclasse2 © 2009 Fernando NIÑO 63 Variables d’instance et classe • Qui a accès aux variables d’instance / classe ? – Tout le monde ! • • Ce n’est pas bon pour l’encapsulation Solution, indiquer celles qui sont privées class MaClasse(object): varclasse1=1 varclasse2=2 __varclasseprivee=3 def __init__(self): self.varinstance=MaClasse.__varclasseprivee self.__privee=None mc.varinstance # OK mc.__privee # Erreur 64 © 2009 Fernando NIÑO Méthodes d’instance et classe • • En général, les méthodes sont d’instance: elles agissent sur les données stockées au sein de chaque objet. Si elles ne le font pas, elle peut être rattaché à la classe: class MaClasse(object): @staticmethod def methodeClasse(): print "je n'ai pas de self" def methodeInstance(self): self.moi = "instance" print self.moi MaClasse.methodeClasse() 65 © 2009 Fernando NIÑO Paramètres • Explicites – on les connaît def fonction(param): • Par défaut – donne une valeur par défaut def fonction(param1, param2=0.): ... fonction(1) # Utilise la valeur par défaut • Paramètres nommés – on donne un nom au paramètre, à l’appel fonction(2, param2 = 34.32) – les paramètres nommés doivent se trouver toujours à la fin. 66 © 2009 Fernando NIÑO Paramètres arbitraires • Nombre variable de paramètres >>> def traiter(*listefichiers): ... for i in listefichiers: ... print 'traite le fichier %s' % i ... >>> traiter('uno','dos','tres','cuatro') traite traite traite traite le le le le fichier fichier fichier fichier uno dos tres cuatro 67 © 2009 Fernando NIÑO Pièges à éviter : copy, deepcopy • Fausse copie – C’est une optimisation ! class Donnees(object): xc=None yc=None def __init__(self): x=None y=None pass d=Donnees() d.x=[1,2,3] d.y=[1,2,3] e=d e.x=[4,5,6] d.x Donnees xc yc d x y e x y 68 © 2009 Fernando NIÑO Deepcopy from copy import deepcopy class Donnees(object): x=None y=None def __init__(self): print "pass" d=Donnees() d.x=[1,2,3] d.y=[1,2,3] e=deepcopy(d) e.x=[4,5,6] d.x 69 © 2009 Fernando NIÑO Retour sur import - Paquetages • Quand on fait import monmodule • il cherche le fichier monmodule.py • Mais, il peut être plus compliqué que ça et être organisé dans un repertoire: monmodule/ mafonction1.py maprocedure.py • Et il faut faire: import monmodule.mafonction1 • ça marche ??? 70 © 2009 Fernando NIÑO Paquetages • Pour faire la différence entre des répertoires lambda et des répertoires structurés pour paquetages, Python cherche toujours un fichier spécial: monmodule/ __init.py__ mafonction1.py maprocedure.py • Et alors, là, il veut bien reconnaître monmodule comme paquetage • Le contenu de __init__.py : code d’initialisation du module, ... ou rien du tout ! 71 © 2009 Fernando NIÑO