Python : Atelier intermédiaire
Sommaire
INTRODUCTION
- Objectifs :
- utiliser la bibliothèque standard et des packages existants
- savoir coder ses propres objets
STANDARD LIBRARY ET PACKAGES
Bibliothèque standard (standard library)
Modules explorés ou abordés pendant ateliers AUF :
- datetime
- pickle
- sqlite3
- re
Modules potentiellement utiles pour administrateurs système :
subprocess
import subprocess out = subprocess.call("grep -rsn 'davin' . > ~/Bureau/davin", shell=True) print out resultat = subprocess.Popen("grep -rsn 'davin' .", shell=True, stdout=subprocess.PIPE).communicate()[0] type(resultat) print resultat
- shell=True pour commande juste en un string
pwd
# http://www.python.org/doc/lj21.html import posix import pwd pwd.getpwall() print 'hello', pwd.getpwuid(posix.getuid())[0] # progfou: et autre détail non négligeable pour nous à l'AuF : pwd fait des appels à la libc, qui passe par NSS, donc ça donne aussi les comptes réseau
socket
# socket.getaddrinfo pour faire de la résolution DNS import socket socket.getaddrinfo('smtp.sn.auf.org', 25)
- os.path
- sys
Autres modules d'intérêt :
- os.system
- zlib
- csv
- json
- uuid
- urllib
- gettext
- pdb
Packages
pypi
numpy, scipy
# fonctions d'optimisation def f(x) : return x**3 - x**2 -10 from scipy import optimize optimize.fsolve(f, 1)
Python African Tour (Dakar, 2009) : Informatique scientifique avec Python
- android
Tutoriel en français (2009)
- nltk
- jabberbot
- django
- auf.django.references
autres
from pyo import * s = Server().boot() s.start() wav = SquareTable() env = CosTable([(0,0), (100,1), (500,.3), (8191,0)]) met = Metro(.125, 12).play() amp = TrigEnv(met, table=env, mul=.1) pit = TrigXnoiseMidi(met, dist='loopseg', x1=20, scale=1, mrange=(48,84)) out = Osc(table=wav, freq=pit, mul=amp).out() s.stop()
CLASSES ET OBJETS
En Python, tout est un objet... on veut donc pouvoir créer nos propres objets en Python.
Classe et objets : structure et données
- Les classes sont une structure, un type de données
- Les objets sont les données, les variables de ce type
- Schéma :
- Monde : objets réels (ou concepts)
- Modélisation du domaine : conceptualisations, (pseudo) UML
Modélisation informatique : classes
Données : objets virtuels
Attributs et méthodes
- La classe est du code informatique qui
structure les données : attributs
un peu comme une table de DB a une structure : colonnes
déclare des traitements possibles sur ces données : méthodes (fonctions dans classe)
un peu comme une DB a traitement informatique possible sur données : procédures stockées
méthodes : fonctions, donc callable
attributs : variables
- nom des attributs et méthodes : visible dans introspection
Créer une Classe
class Personne(): pass
- class
convention de nommage : CamelCase
PersonneMorale : ok
- personne_morale : pas ok
self
représente l'objet en cours dans le code de la Classe
nom générique : veut dire "quelque soit l'objet en cours, voici ce que je veux faire de cet objet"
équivalent à this en Java ou PHP
Créer méthode d'initialisation d'objet
class Personne(): def __init__(self, nom, prenom=""): self.nom = nom self.prenom = prenom
- self : toujours comme premier argument
- autres paramètres reçus lors d'initialisation (nom, prenom) sont stockés sur l'objet
- les attributs 'nom' et 'prenom' sur l'objet : self.nom, self.prenom, sont des variables avant une valeur propre à l'objet
Créer une (autre) méthode
class Personne(): def __init__(self, nom, prenom=""): self.nom = nom self.prenom = prenom def nom_complet(self): return "%s %s" % (self.nom.upper(), self.prenom)
- Convention de nommage : lower_case
NomComplet : pas ok
- nom_complet : ok
- self : premier paramètre
- tout le reste : c'est simplement une fonction
- (paramètres en input, traitement, return pour output)
CRUD d'objets
Create : création d'objet
davin = Personne(nom="Baragiotta", prenom="Davin")
On utilise la classe pour créer un objet de cette classe.On passe en paramètre les infos nécessaires à __init__() pour créer l'objet.
vérification des attributs de l'objet davin
davin. [+ tab] # ipython davin.nom davin.prenom
Update : modification de l'objet
davin.prenom = "Daniel" davin.prenom
Delete : suppression de l'objet
del davin
Retrieve : récupération de l'objet n'a pas de sens si on a de la permanence de l'information.
- Typiquement, on voudra stocker nos objets dans des bases de données en liant nos Classes à des tables. C'est ce que les ORM (Object-relational-mapper) font. Atelier Django montre comment récupérer les objets stockés dans DB.
Attributs et méthodes : de classe et d'objet
Dans l'exemple précédant, nous avons vu les attributs et méthodes d'un objet :
objet.attribut
davin.nom
objet.methode()
davin.nom_complet()
Il existe aussi des attributs et méthodes de classe :
class Personne(): """Représente les personnes""" definition = "Une personne est un individu physique, un humain quoi!" def __init__(self, nom, prenom=""): self.nom = nom self.prenom = prenom def nom_complet(self): return "%s %s" % (self.nom.upper(), self.prenom) @staticmethod def wordnet_synonyme(): wordnet_syn = "Individual" # fake ;) return wordnet_syn
Classe.attribut
Personne.definition
Classe.methode()
Personne.wordnet_synonyme()
Il est à noter que :
l'attribut de classe est déclaré directement sous la classe...
.. pas dans la méthode __init__() : car cet attribut n'est pas propre à un objet
la méthode de classe ne prend pas l'argument : self
pour déclarer une méthode de classe, il faut utiliser le décorateur @staticmethod
tous les objets d'une classe ont accès aux attributs et méthodes (génériques) de la classe.
- la classe, par contre, n'a accès qu'a ses propres attributs et méthodes.
davin = Personne(nom="Baragiotta", prenom="Davin") pascal = Personne(nom="Bou Nassar", prenom="Pascal") davin.definition 'Une personne est un individu physique, un humain quoi!' pascal.definition 'Une personne est un individu physique, un humain quoi!' Personne.definition 'Une personne est un individu physique, un humain quoi!' davin.definition == pascal.definition == Personne.definition True davin.wordnet_synonyme() 'Individual' pascal.wordnet_synonyme() 'Individual' In [11]: Personne.nom --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) /home/giotta/Bureau/<ipython console> in <module>() AttributeError: class Personne has no attribute 'nom' In [12]: Personne.prenom --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) /home/giotta/Bureau/<ipython console> in <module>() AttributeError: class Personne has no attribute 'prenom' In [13]: Personne.nom_complet() --------------------------------------------------------------------------- TypeError Traceback (most recent call last) /home/giotta/Bureau/<ipython console> in <module>() TypeError: unbound method nom_complet() must be called with Personne instance as first argument (got nothing instead)
Héritage
On peut créer une hiérarchie de classe, avec des SousClasse qui hérite des ClasseParent.
Syntaxe d'héritage
- On déclare les classes héritées en paramètre de la classe (entre les parenthèses de la définition de classe).
La classe suprême en Python est la classe object.
On peut donc faire hériter nos classes de cet objet au sommet de la hiérarchie
class Personne(object): pass class Chat(): pass Chat. [+tab] # ipython Personne. [+tab] # ipython
- dans cet exemple, on voit que Personne a plus de noms (attributs, méthodes) dans son espace de nom...
... Personne a hérité des attributs et méthodes de object
Attributs et méthodes de ClasseParent sont hérités
Une sous-classe hérite donc des attributs et méthodes de sa classe parent
class Personne(object): """Représente les personnes""" definition = "Une personne est un individu physique, un humain quoi!" def __init__(self, nom, prenom=""): self.nom = nom self.prenom = prenom def nom_complet(self): return "%s %s" % (self.nom.upper(), self.prenom) @staticmethod def wordnet_synonyme(): wordnet_syn = "Individual" # fake ;) return wordnet_syn class Professeur(Personne): pass Personne. [+tab] # ipython Professeur. [+tab] # ipython
__init__() d'une SousClasse
- si une classe hérite :
son __init__() doit appeler __init__() de son parent
en passant bien tous les arguments requis par la ClasseParent...
... incluant self
class Personne(): """Représente les personnes""" definition = "Une personne est un individu physique, un humain quoi!" def __init__(self, nom, prenom=""): self.nom = nom self.prenom = prenom def nom_complet(self): return "%s %s" % (self.nom.upper(), self.prenom) @staticmethod def wordnet_synonyme(): wordnet_syn = "Individual" # fake ;) return wordnet_syn class Professeur(Personne): def __init__(self, nom, prenom="", universite=""): self.universite = universite Personne.__init__(self, nom, prenom) In [2]: davin = Personne(nom="Baragiotta", prenom="Davin") In [3]: prof = Professeur(nom="Lemay", prenom="Paul", universite="UQAM") In [4]: prof. prof.__class__ prof.__module__ prof.nom_complet prof.wordnet_synonyme prof.__doc__ prof.definition prof.prenom prof.__init__ prof.nom prof.univesite In [5]: davin. davin.__class__ davin.__module__ davin.nom_complet davin.__doc__ davin.definition davin.prenom davin.__init__ davin.nom davin.wordnet_synonyme
AUTRES NOTIONS PYTHON
Décorateurs
Les décorateurs sont des fonctions qui "wrappent" d'autres fonctions :
- ils permettent notamment de contrôler l'accès aux fonctions wrappées
- mais pourraient aussi modifier input et output de ces fonctions
Exemple de décorateur conçu pour contrôler l'accès : is_admin
def is_admin(fn): def inner(admin, *args, **kwargs): if admin: return fn(*args, **kwargs) else : return "Nope" return inner @is_admin def salut(nom): return "salut %s" % nom
Pour décorer une fonction : décorer avec @nom_fonction_qui_decore
Il faut appeler la fonction décorée aussi avec les paramètres requis par la fonction qui décore.
In [10]: admin = True In [11]: salut(admin, 'Davin') Out[11]: 'salut Davin' In [12]: admin = False In [13]: salut(admin, 'Davin') Out[13]: 'Nope'
Exceptions
Pour gérer les exceptions qui peuvent être levées lors de l'exécution du code...
.. il faut utiliser la structure du langage : try et except
In [18]: davin = Personne(nom="Baragiotta", prenom="Davin") In [19]: davin.nationalite --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) /home/giotta/Bureau/<ipython console> in <module>() AttributeError: Personne instance has no attribute 'nationalite' In [20]: try: ....: davin.nationalite ....: except AttributeError: ....: davin.nationalite = None ....: ....: In [21]: davin.nationalite In [22]:
après le mot except on fournit le type d'exception qu'on veut gérer, ex.: AttributeError
EXERCICE
- créer une classe Personne
- créer une méthode nom_complet() (ou fullname() ) sur la classe Personne retournant le nom complet d'un personne
- créer une classe Professeur qui hérite de Personne
- créer un attribut "formations" pour les objets de la classe Professeur : c'est la liste des formations que donne le prof
- tester comment ajouter ou supprimer une formation à un professeur : quelle approche la plus simple?
- créer une méthode Professeur.ajout_formation() ?
- ou simplement exploiter les méthodes de liste : Professeur.formations.append() ?
CONCLUSION
- ne pas réinventer la roue : utiliser l'existant
- DIY (do-it-yourself) : pour le reste, faites du "sur mesure"
- yalla!