Modifications entre les versions 28 et 29
Version 28 à la date du 2012-02-25 02:05:26
Taille: 14116
Éditeur: DavinBaragiotta
Commentaire: exceptions
Version 29 à la date du 2012-08-27 07:27:18
Taille: 14120
Éditeur: DavinBaragiotta
Commentaire:
Texte supprimé. Texte ajouté.
Ligne 195: Ligne 195:
 * '''Retrieve''' : récupération de l'objet n'a de sens si on a de la permanence de l'information.  * '''Retrieve''' : récupération de l'objet n'a pas de sens si on a de la permanence de l'information.

Python : Atelier intermédiaire


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
  • email
  • uuid
  • urllib
  • gettext
  • pdb

Packages

pypi

http://pypi.auf.org/

  • auf.django.references

autres

  • Fabric, Cuisine, Watchdog

  • pyo

    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

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
  • 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!

Ateliers/2012-02-24/Python/Plan (dernière édition le 2012-08-27 07:27:18 par DavinBaragiotta)