LinuxPedia

Wiki libre et indépendant dédié à GNU-Linux et BSD.

Outils pour utilisateurs

Outils du site


expert:python_objet

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

expert:python_objet [2018/11/17 13:53] (Version actuelle)
Ligne 1: Ligne 1:
 +====== La programmation Orientée objet: Les bases avec python ======
  
 +=== NOTES ===
 +Je ne vais pas m'​étendre ici sur les grands principe de la programmation,​ ce tuto est une introduction,​ on va faire quelques manips de base pour vous faire acquérir la notion d'​objet. Il est donc volontairement très incomplet. Je vous recommande le lecture préalable de cet article:
 +
 +  * [[expert:​developpement]]
 +
 +== Pourquoi python? ==
 +Ce tuto a pour objectif de vous faire apprendre les bases de la programmation orientée objet. Pour ce faire, il faut bien choisir un langage de programmation.
 +
 +Python a des qualités qui en font le langage idéal pour commencer l'​objet:​
 +  * typage dynamique : on peut s'​épargner l'​apprentisage des types de données (il faudra y passer après quand même)
 +  * full-objet : on peut s'​immerger directement dans le monde des objets
 +  * syntaxe simple
 +
 +Enfin, python a beau être un langage didactique, ce n'est pas qu'un gadget scolaire, il est largement utilisé pour coder de vraies applications.
 +
 +== Version de python pour ce tuto ==
 +
 +Pour le tuto, j'​utilise python en version 2.6
 +
 +La raison de ce choix est que c'est la version stable officielle de la debian actuelle. Par conséquent,​ c'est celle que vous trouverez sur tous les serveurs.
 +
 +J'​essaye cependant de suivre le guide des bonnes pratiques de python, les exemples devraient donc être compatibles avec la version 3.
 +
 +===== Qu'​est-ce que la programmation orientée objet? =====
 +
 +Je vous propose ici d'​apprendre la programmation en commençant par l'​objet et non par les précédures,​ a contrario de la plupart des cours que vous pourrez trouver sur la programmation,​ même en orienté objet. Cela me parait plus naturel, d'​apprendre l'​objet en commençant par l'​objet.
 +
 +La programmation orientée objet est un paradigme de programmation. C'est un style de programmation qui va conditionner la manière de traiter les problèmes. Le paradigme objet est orienté vers l'​organisation des données, au contraire du procédural qui est orienté vers le traitement des données.
 +
 +==== Des classes et des objets ====
 +
 +Une classe est une sorte de modèle sur lequel on peut se baser pour construire les objets.
 +
 +Par exemple, prenons un cercle. Je vais définir une classe cercle avec une variable pour le rayon: R. La classe cercle va me servir pour fabriquer des objets cercles, autant que je veux:
 +<​code>​
 +class Cercle():
 +    R = 2
 +# ici, je définis la class Cercle
 +
 +
 +monCercle = Cercle()
 +# Là, je crée un objet à partir de la classe Cercle
 +</​code>​
 +Les lignes qui commencent par # sont des commentaires,​ elles ne seront pas traitées par l'​interpréteur.
 +==== Les méthodes ====
 +
 +On peut les appeler indiféramment méthode, procédure ou fonction. En python, cela n'a pas d'​importance. Il est cependant convenu d'​appeler méthode une fonction définie dans une classe.
 +
 +Nous pouvons rajouter dans notre classe "​cercle"​ une méthode qui va calculer le périmètre du cercle et le stocker dans une variable qu'on va appeller P.
 +
 +La procédure est ce qui transforme le contenu de la variable R en variable P. Ici, c'est simple, c'est le calcul: P = 2*3.14*R :
 +<​code>​
 +# definition de la classe:
 +class Cercle():
 +    R = 2
 +
 +    # ma méthode:
 +    def peri(self):
 +        # variable P interne à la fonction:
 +        P = 2*3.14*self.R
 +        return P
 +</​code>​
 +===== De quoi a-t-on besoin pour ce tuto? =====
 +
 +=== Python, bien sûr! ===
 +
 +Il vous faut installer python, bien évidemment. Il y a de fortes chance qu'il soit déjà présent sur votre système car de nombreux outils utilisent python. Vous avez besoin de la version 2.6 et c'est tout.
 +
 +=== Un émulateur de terminal bien configuré ===
 +
 +L'​émulateur de terminal est l'​outil le plus important d'un technicien linux. Il faut donc bien le choisir et surtout bien le configurer. Par exemple, certains emulateurs (gnome-terminal,​ konsole, etc) ont par défaut des raccourcis clavier qui rentrent en conflit avec de nombreux outils en mode console.
 +
 +Je ne recommande pas es outils qui incluent trop de choses inutiles. La règle pour un bon émulateur est qu'il se contente d'​émuler des terminaux. Il n'y a pas besoin de gadgets, votre environnement de bureau est là pour ça!
 +
 +Il est également important de le rendre visuellement confortable,​ vous allez y passer un certain temps, alors un peu de tuning rendra son usage plus agréable.
 +
 +=== Un interpréteur avancé: ipython ===
 +
 +Python inclut par défaut deux interpréteurs:​
 +  * L'​interpréteur en ligne de commande, qu'on appelle par la commande "​python":​ sans argument, celui-ci vous place dans un mode intéractif où vous pouvez directement entrer votre code qui sera aussitôt interprété.
 +  * L'​interpréteur graphique idle, qui fait la même chose mais dans une interface graphique tk, avec les fonctionnalités avancées qu'on peut attendre d'une interface graphique.
 +
 +Toutefois, il est plus pratique d'​utiliser un interpréteur plus évolué. Votre éditeur de texte permet sans doute de faire cela. Geany, par exemple, tout en restant simplicime, inclut une console python.
 +
 +Pour les besoin du tuto, on va commencer en console (pourquoi? parce qu'on est des durs!) et un interpréteur avancé existe: ipython
 +
 +Une de fonctionnalités intéressantes de ipython est d'​inclure diverses commandes système. Vous pouvez donc écrire directement des fichiers, vous promener dans l'​arborescence et lister les répertoires depuis ipython. En fait, si vous l'​aimez bien, vous pouvez même en faire votre interpréteur de commande par défaut, au lieu de bash!
 +
 +Allez le chercher avec votre gestionnaire de paquet favori et installez-le!
 +
 +=== Un éditeur de texte ===
 +
 +En programmation,​ vous aurez toujours besoin d'un éditeur de texte. Python est un langage interprété,​ vous pouvez l'​utiliser directement avec l'​interpréteur mais tôt ou tard, il faudra bien écrire vos programmes en dur.
 +
 +L'​éditeur de texte est un composant très important pour le programmeur,​ il peut requérir un apprentissage à lui tout seul. Ce n'est en aucun cas une perte de temps! Prennez le temps d'​apprendre à utiliser votre éditeur de texte.
 +
 +C'est donc le momment de faire un choix: soit vous êtes un vrai dur de dur et vous apprennez à utiliser un éditeur de texte en console: vim, emacs, etc; soit vous choisissez un éditeur graphique: geany, kate, etc.
 +
 +===== On se lance? =====
 +
 +Assez de bavardage, on va s'​amuser un peu, OK?
 +
 +Vous avez besoin d'​ouvrir une console. Dans cette console, vous entrez la commande:
 +
 +<​code>​ipython</​code>​
 +
 +Et nous voilà enfin au cœur du sujet. Quelques petites choses à savoir sur la syntaxe python:
 +  * Les sauts de ligne font partie du langage
 +  * L'​indentation fait partie du langage: une indentation,​ c'est quatre espaces au début d'une ligne
 +  * On passe une ligne après une méthode
 +  * On passe deux lignes après avoir déclarer une classe
 +Ipython mettra automatiquement les indentations et se comportera de la manière attendue si vous respectez ces règles.
 +
 +Pour le quitter, comme pour l'​interpreteur standard: <​ctrl>​ + d
 +===== Jouons avec les classes et les objets =====
 +
 +Je vais utliser une notation [[expert:​uml|UML]] pour décrire les classes et les objets.
 +
 +==== Une classe ====
 +
 +Reprenons notre classe cercle:
 +<​code>​
 ++------------------+
 +|  Cercle ​         |
 ++------------------|
 +|  R = 2           |
 ++------------------|
 +|                  |
 ++------------------+
 +</​code>​
 +La première case représente le nom de la classe. La seconde les variables de la classe. La troisièmes les méthodes de la classe. Pour l'​instant,​ c'est vide.
 +
 +Le code qui va correspondre à ce modèle:
 +<​code>​
 +class Cercle():
 +    R = 2
 +</​code>​
 +La méthode class qu'on utilise ici sert à créer... des classes. On donne ensuite le nom de la classe et on laisse les parenthèses vide, on s'en servira plus tard. Sans oublier les doubles points.
 +
 +À la ligne, notez l'​indentation,​ on déclare notre variable R et on lui attribue une valeur arbitraire.
 +
 +N'​oubliez pas de passez deux lignes à la fin de la classe.
 +
 +=== Un peu d'​introspection ===
 +
 +Une des particularités très appréciée de python est l'​introspection. Depuis la console python, vous pouvez inspecter vos classes, vos objets, et vous avez accès à la documentation standardisée de chaque element du langage, chaque classe et chaque méthode de classe.
 +
 +Nous allons donc demander à l'​interpréteur ce qu'il en est de notre classe nouvellement créée, essayez les directives suivantes:
 +<​code>​type(Cercle)
 +dir(Cercle)
 +help(Cercle)</​code>​
 +Touche q pour quiter l'​écran help.
 +
 +La directive type() renvoie ce résultat: <type '​classobj'>​ Ceci peut vous paraître étrange. Est-ce une classe ou un objet? Réponse: c'est les deux! Hé oui, en python, tout est objet, même les classes sont des objets.
 +
 +dir() vous renvoie aussi un peu plus d'​élements que vous en attendiez. Ceux-ci sont rajoutés à la création de la classe. On y reviendra plus tard.
 +
 +==== Un objet ====
 +
 +On dit aussi "​instance de classe"​.
 +
 +Maintenant que nous avons notre classe, créons un objet à partir de cette classe:
 +<​code>​monCercle = Cercle()</​code>​
 +Facile, non? Vous pouvez essayer encore les directives type(), dir() et help()
 +Pour connaitre la valeur d'un élément, vous pouvez entrer simplement:
 +<​code>​monCercle.R</​code>​
 +Dans un vrai programme, vous ne ferez pas cela, cela fonctionne en interpreteur par facilité mais à l'​exécution d'un script, vous vous prendrez un traceback, voilà comment afficher proprement une valeur à l'​écran:​
 +<​code>​print(monCercle.R)</​code>​
 +
 +=== La méthode spéciale __init__() ===
 +Maintenant qu'on sait créer une classe et un objet, on va vouloir créer des cercle de tailles différentes (pas uniquement des cercle de 2). On peut changer la variable R comme ceci:
 +<​code>​monCercle.R = 3</​code>​
 +Cependant, il serait sans doute plus malin de déterminer la taille du cercle dès la création de l'​objet,​ non? Rien de plus simple, il suffit d'​utiliser la méthode spéciale __init__() Vous l'avez vue dans les résultats de dir(cercle),​ __init__ est ce qu'on appelle un constructeur,​ il fait systématiquement partie de toute classe, c'est une méthode dont le rôle est de consrtruire les objets. Voici ce qu'on va faire:
 +<​code>​
 +class Cercle():
 +    R = 0
 +
 +    def __init__(self,​ monRayon):
 +        self.R = monRayon
 +</​code>​
 +L'​instruction def sert à definir une méthode. Dans la déclaration d'une méthode, entre parenthèses on note les arguments. self correspond à l'​objet lui-même, nomRayon est une variable à laquel nous attribuerons la valeur d'un argument supplémentaire que nous allons passer au constructeur lors de son appel.
 +
 +Ensuite, le code de la méthode: nous allons attribuer à la variable R de l'​objet que nous créons la valeur de la variable monRayon passée en argument.
 +
 +Créons donc notre nouvel objet:
 +<​code>​monCercle = Cercle(6)</​code>​
 +Le tour est joué!
 +
 +== Note ==
 +Python est un langage très très souple, il permet de récrire les classes, de recréer les objets et de modifier les variables à la volée.
 +
 +Dans l'​exemple,​ nous venons de modifier la classe cercle. Mais l'​objet monCercle que nous avions d'​abord créé garde ses propriétés initiale. Nous devons donc recréer cet objet pour qu'il tienne compte des modification apportées au constructeur.
 +
 +==== Une méthode ====
 +
 +Essayons maintenant de faire notre propre méthode à nous tout seul. Cette méthode va calculer le périmètre du cercle: 2*pi*R
 +
 +=== Importons pi! ===
 +
 +Comme on est des durs, on va pas se contenter de noter 3.14 à chaque fois qu'on a besoin de pi, hein? Il se trouve que pi fait partie d'un module python appelé "​math"​. Les module ne sont pas chargés par défaut, il nous suffit donc d'​importer pi depuis le module math:
 +<​code>​from math import pi</​code>​
 +Maintenant, essayez:
 +<​code>​print(pi)</​code>​
 +Ceci nous permet de voire comment on importe dans l'​interpréteur les modules suplémentaires. Ici, on se contente d'​importer pi, puisqu'​on n'a besoin que de ça! Pour importer le module math entier, on aurait fait:
 +<​code>​import math</​code>​
 +À ce moment là, on utilise pi de la manière suivante:
 +<​code>​print(math.pi)</​code>​
 +
 +=== Calculons le périmètre ===
 +
 +Ouïe! une formule... Allez, je vous la donne: 2*pi*R
 +
 +Ajoutons donc notre méthode à notre code existant:
 +<​code>​
 +class Cercle():
 +    R = 0
 +
 +    def __init__(self,​ monRayon):
 +        self.R = monRayon
 +
 +    def peri(self):
 +        P = 2*pi*self.R
 +        return P
 +</​code>​
 +Notez qu'​encore une fois nous passons self (l'​objet lui-même) en argument à la fonction. P est une variable interne à la méthode peri(), elle n'​existe pas en dehors. En revanche, R est une variable de l'​objet,​ on l'​appelle donc dans la méthode avec self.R, ce qui nécessite que l'​objet lui-même soit passé en argument à la méthode.
 +
 +La directive return indique que la méthode doit renvoyer la valeur de P. On aurait aussi pu écrire:
 +
 +<​code>​return 2*pi*self.R</​code>​
 +
 +Ceci parait plus simple de prime abord mais il vaut mieux toujours prévoire que le code va se compliquer et définir ici une variable permettra par la suite de faire plusieurs opérations avec elle sans avoir à récrire plusieurs fois la formule. Par exemple, nous pourrions stocker P dans l'​objet:​
 +<​code>​
 +def peri(self):
 +    P = 2*pi*self.R
 +    self.P = P
 +    return P
 +</​code>​
 +
 +Voici à quoi ressemble notre modèle, maintenant:
 +<​code>​
 ++------------------+
 +|  Cercle ​         |
 ++------------------|
 +|  R = 2           |
 ++------------------|
 +|  init(monRayon) ​ |
 +|  peri() ​         |
 ++------------------+
 +</​code>​
 +
 +=== Utilisons notre nouvelle méthode ===
 +
 +Pour cela, on va commencer par recréer monCercle:
 +<​code>​monCercle = Cercle(5)
 +print(monCercle.peri())</​code>​
 +
 +===== La notion d'​héritage =====
 +
 +==== Note: le flux ====
 +
 +Je n'ai pas parlé jusqu'​ici du flux mais c'est l'​occasion de glisser un mot. Quand on execute un script, celui-ci est lu, du début à la fin, le flux des données doit donc être pensé de cette façon. L'​héritable est une relation forte d'une classe vers l'​autre,​ l'​ordre dans laquelle vous les déclarez devient donc important.
 +
 +==== Héritage simple ====
 +
 +L'​héritage est un type de relation où une classe prend tous les attributs et méthodes d'une autre. Comme un exemple vaut mieux qu'une longue explication,​ en voilà un qui va vous parler un peu plus.
 +
 +Nous créons un jeu de rôle. L'​objet personnage pourrait ressembler à ceci:
 +<​code>​
 +from random import randint
 +
 +class Rerso():
 +    force = 0
 +    endur = 0
 +
 +    def __init__(self):​
 +        self.force = randint(1,​20)
 +        self.endur = randint(1,​100)
 +</​code>​
 +Le code devrait vous paraître simple. Petite spécificité,​ nous commençons par importer la méthode randint du module random pour émuler les jets de dé.
 +
 +Notre jeu inclue deux races: les nains et les elfes. Les nains et les elfes sont des personnages,​ on va donc les faire hériter de la classe personnage ses caractéristiques. Pour ce faire, lorsqu'​on déclare la classe, on rajoute le nom de la classe mère entre les parethèses.
 +<​code>​
 +from random import randint
 +
 +class Perso():
 +    force = 0
 +    endur = 0
 +
 +
 +class Nain(Perso):​
 +    barbe = 0
 +
 +    def __init__(self):​
 +        self.barbe = randint (50,100)
 +        self.force = randint(3,​20)
 +        self.endur = randint(4,​100)
 +
 +
 +class Elf(Perso):
 +    cheveux = 0
 +
 +    def __init__(self):​
 +        self.cheveux = randint (50,100)
 +        self.force = randint(2,​20)
 +        self.endur = randint(4,​100)
 +</​code>​
 +
 +Comme la classe perso ne va plus nous servir à créer directement des personnage, on lui enlève son constructeur qui ne sert plus à rien. En revanche, on va pouvoir personaliser les constructeurs des classes filles.
 +
 +Pour l'​exemple,​ on ajoute ici une caractéristique spécifique à chaque classe, la taille de la barbe des nains et celles des cheveux des elfes.
 +
 +Le modèle simplifié ressemble à ceci:
 +<​code>​
 +                         ​+--------+
 ++---------+ ​    ​+--------| ​ Nain  |
 +|  Perso  |<​|---| ​       +--------+
 ++---------+ ​    |
 +                |        +--------+
 +                +--------| ​ Elf   |
 +                         ​+--------+
 +</​code>​
 +Maintenant, créez des instances des classe nain et elf et utilisez l'​introspection pour connaitre leurs caractéristiques:​
 +<​code>​
 +gimli=Nain()
 +tafiole=Elf()
 +dir(gimli)
 +['​__doc__',​ '​__init__',​ '​__module__',​ '​barbe',​ '​endur',​ '​force'​]
 +</​code>​
 +Vous voyez ici que l'​objet gimli a hérité de la classe perso les variables force et endur.
 +
 +Vous pouvez maintenant vous amuser à pousser un peu le concept, rajouter des nouveaux attributs à ces classes, créer des nouvelles races, etc.
 +==== Héritage multiple ====
 +
 +Python permet l'​héritage multiple. Ça vous semble peut-être évident mais peu de langage le permettent. Par exemple:
 +
 +<​code>​
 +class Papa():
 +    SEXE = "​m"​
 +
 +
 +class Maman():
 +    SEXE = "​f"​
 +
 +
 +class Enfant(Papa,​ Maman):
 +    pass
 +</​code>​
 +
 +Ici, on illustre bien le problème que cela pose. Les deux classes ont une variable constante qui porte le même nom: de laquelle va hériter l'​objet enfant? ​
 +
 +Pour résoudre ce problème, on peut:
 +  * Créer une méthode pour fusionner les eléments complexes (les fonctions, par exemple)
 +  * Utiliser la surcharge
 +==== La surcharge d'​opérateurs ====
 +
 +La surcharge consiste à redéfinir un élement. Quand une classe hérite d'une autre, vous pouvez vouloir modifier une une variable ou une fonction. On le fait simpement en redéclarant celle-ci dans la classe fille:
 +
 +<​code>​
 +Classe Papa():
 +    def dit():
 +        print("​je suis ton père"​)
 +
 +
 +Classe enfant(Papa):​
 +    def dit():
 +        print("​NOOOOON!"​)
 +</​code>​
 +
 +
 +====== Aller plus loin avec python ======
 +
 +Pour aller plus loin, nous allons utiliser notre éditeur de texte pour écrire les programmes. Nous continuerons tout de méme à employer l'​interpreteur mais surtout pour les executer.
 +
 +===== Quelques recommandations =====
 +
 +==== Les bonnes pratiques ====
 +
 +=== KISS ===
 +
 +Keep It Simple, Stupid! (Laisse ça simple, imbécile!)
 +
 +Souvenez-vous du rasoir d'​Okham. Pas la peine d'​écrire le code au kilomètre, gardez-le toujours le plus simple possible. Si il devient trop compliqué ou trop important, vous avez sans doute besoin de faire une bibliothèque.
 +
 +=== Syntaxe ===
 +
 +En python, l'​indentation et les fins de ligne font partie intégrante de la syntaxe. Quand on ecrit une classe, on est obligé de sauter des lignes et d'​inteter le contenu de la classe. Dans beaucoup de langage, ce n'est pas une obligation. Le fins de ligne sont représentées par des ";"​ et le contenu d'une classe est encadrée par des accolades. On peut ainsi écrire:
 +
 +<​code>​class Perso {int $force; int $endu;}
 +# ou encore
 +class Perso
 +{
 +int $force;int $endu;
 +}
 +</​code>​
 +
 +Seulement, on n'est que rarement seul à travailler sur un projet. Quand le code commence à devenir vraiment compliqué (imaginez la tailles des classe si vous transcrivez la totalité des règle de AD&D), si chacun utilise son propre style, cela devient vite invivable. Croyez-moi, il n'y a rien de plus agaçant que de devoir reprendre du code en vrac!
 +
 +Dans les logiciels libres, c'est encore plus flagrant, l'​aspect communautaire fait que les développeurs vont et viennent et le nombre total de personne qui a travaillé sur un projet est souvent très impressionant. Des règles consensuelles existent donc pour que le code soit lisible par tous rapidement.
 +
 +De plus, vous vous rendrez vite compte qu'on a nous aussi une capacité de mémorisation limitée. Quand on a le nez dans son programme, on sait bien évidemment à quoi correspond quoi. Mais on développe toujours plusieurs choses, on passe d'un projet à l'​autre,​ et quand on reprend son programme, c'est beaucoup moins évident de s'y retrouver si on a pas tout bien organisé.
 +
 +C'est en tenant compte de ces habitudes que python a été créé. Le code python est ainsi toujours très lisible. En apprenant la programmation orientée objet avec python, vous prennez des bonnes habitudes.
 +
 +Un certain nombre de conventions,​ cependant, ne font pas partie des obligations mais sont tout de même recommandées:​
 +
 +  * Laisser deux lignes vides après une classe
 +  * Un espace après une virgule
 +  * Un espace de chaque côté des opérateurs logiques ( = != | & )
 +  * Utiliser quatre espaces au lieu d'une tabulation pour les indentations
 +  * Pas d'​espace aux ouvertures et fermeture de parenthèses
 +  * Des lignes de 79 caractères (originellement,​ les terminaux faisaient une taille de 80 caractères. Cette convention est gardée surtout parce qu'​elle oblige à ne pas faire des lignes à ralonge et à casser les instructions en plus petits morceaux. De plus, même pour la doc et les commentaires,​ vous vous appercevrez que c'est plus lisible ainsi)
 +
 +=== Conventions de nommage ===
 +
 +  * Les classes : première lettre en majuscule, le reste en minuscule
 +  * Les variables de préférence en minuscule sauf si cela vous permet de mieux l'​identifier (exemple montreGousset)
 +  * Modules et packages en minuscule.
 +
 +D'une manière générale, assurez-vous qu'il y ait une certaine cohérence dans les noms, que ceux-ci soient significatifs. Évitez d'​appeller vos varibles a, b, c, d, etc. Évitez quand même les noms à ralonge. Pensez toujours votre code comme si quelqu'​un allait le lire et le travailler après vous, même si vous êtes seul pour l'​instant.
 +
 +=== Encapsulation des données ===
 +
 +L'​encapsulation des données consiste à faire en sorte qu'on n'​accède aux variables directement depuis l'​extérieur de l'​objet. Python n'a pas de mécanisme de contrôle de l'​encapsulation,​ on peut toujours acceder aux variables de l'​extérieur,​ les modifier, les surcharger à la main.
 +
 +Si cela s'​avère pratique pour le débugage, c'est une pratique à proscrire totalement dans l'​application finale. Il faut créer une méthode pour chaque type d'​intéraction avec les variables d'un objet. De la même manière qu'on ne demande pas à un programme de modifier ses classes à la volée, de manière à assurer la persistance des données.
 +
 +Ces méthodes s'​appellent en français des accesseurs et des mutateurs. Termes barabares que l'on emploie que rarement (j'ai dû chercher sur wikipédia pour les retrouver). On dit plutôt des geteurs et des seteurs, car traditionnellement,​ les noms de ces méthodes commencent par get ou set.
 +
 +Pour vous expliquer l'​importance de ce principe, rien ne vaut un exemple:
 +<​code>​
 +classe Compteur():
 +    nb = 0
 +
 +def getNb(self):​
 +    nb = nb +1
 +    return nb
 +
 +
 +zigzag = compteur()
 +zigzag.getNb()
 +>1
 +zigzag.getNb()
 +>2
 +zigzag.getNb()
 +>3
 +zigzag.nb
 +>3
 +zigzag.nb
 +>3
 +</​code>​
 +Ici, c'est simple, on veut compter le nombre de fois que le programme accède à une variable. Si le programme accède directement à la variable, ça ne fonctionne pas.
 +
 +=== Importation ===
 +
 +Il existe différentes manières d'​importer les modules:
 +<​code>​from math import pi</​code>​
 +Ici on importe uniquement la variable pi du module math
 +<​code>​import math</​code>​
 +Ici, on importe le module math. Pour acceder à pi, il faudra procéder comme suit:
 +<​code>​math.pi</​code>​
 +Ce n'est pas recommandé,​ il vaut mieux n'​importer que ce dont on a besoin. En effet, chaque élement chargé prendra de la place en mémoire. Si vous importez chaque module entièrement,​ vous pouvez très vite gaspiller beaucoup de place.
 +
 +De la même façon:
 +<​code>​from math import *</​code>​
 +Là, on peut toujour appeller tous les élements du module directement mais en plus de charger la mémoire, si vous faites ça sur plusieurs module, il est possible que les noms des éléments rentrent en conflit. Dans ce cas, c'est le dernier chargé qui écrase les autre mais je vous laisse imaginer le bazar.
 +
 +D'​ailleurs,​ vous pouvez changer le nom d'un import de la manière suivante:
 +<​code>​from math import pi as toto</​code>​
 +Il faudra par la suite utiliser le nom "​toto"​ au lieu de "​pi"​
 +
 +=== Commentez! ===
 +
 +Les commentaires sont des éléments importants. Il ne font rien en eux-même mais permettent de s'y retrouver dans le code et donnent des informations utiles pour les autres programmeurs et pour vous-même. Un commentaire est une ligne qui commance par #
 +
 +Il ne faut pas hésiter à en mettre à chaque fois que cela vous parait pertinent.
 +
 +=== Documentez! ===
 +
 +Vous avez découvert l'​introspection un peu plus haut. Avec le temps, vous l'​apprécierez de plus en plus. Vous importez un module et pour savoir comment l'​utiliser,​ quelles classes il contient, etc, dir() et help() sont des outils magiques!
 +
 +Hé bien, une chose qui rend l'​introspection si utile, c'est que les dev rajoutent des commentaire spéciaux destinés à apparaitre dans les outils d'​introspection. Ils ajoutent leur documentation dans le code lui-même. Maintenant que vous faites partie de la grande famille des développeurs,​ cela fait également partie de vos responsabilités.
 +
 +Voici comment rajouter un element à la pydoc:
 +<​code>​
 +"""​
 +Ici, je documente une fonction ou une classe
 +"""​
 +</​code>​
 +
 +Inspirez-vous de la pydoc existante et que vous utilisez avec la commande help()
 +
 +Tâchez de vous exprimer en anglais et de vérifier que votre anglais technique est correct. En anglais, c'est une convention. On va pas troller à propos de l'​égémonie de l'​anglais à travers le monde, le fait est que tout le monde le parle en informatique. Imaginez ce que ça donnerait si chacun rédigeait sa doc dans sa langue natale... Personne n'a envie d'​être obligé d'​apprendre l'​italien,​ l'​espagnol,​ le chinois, etc, pour pouvoir lire la doc! C'est sûrement intéressant mais bon...
 +
 +===== Créer vos propres modules et bibliothèques =====
 +
 +Une bibliothèque est un ensemble d'​élements rangés comme dans un catalogue dans lequel on va puiser à la demande, chaque fois qu'on en a besoin. Un bibliothèqe est statique, elle ne fait rien d'​elle-même.
 +
 +Un module en revanche, est un composant actif qui vient se grefer au programme.
 +
 +La différence entre module et bibliothèque python est presque philosophique. On peut dire encore package (correspond à la dénomination UML). Il n'y a pas de bibliothèque à proprement parler en python.
 +
 +Tout fichier python est en lui-même un module, vous pouvez l'​importer directement avec l'​instruction import.
 +
 +Pour créer un module plus important, on peut stocker plusieurs fichier python dans un répertoire. On rajoute alors un fichier __init__.py au même niveau. Ce fichier peut rester vide. Si besoin est, il contiendra les méthodes supplémentaire propres à l'​importation ou permettra d'​importer certaines dépendances,​ aussi.
 +
 +==== Un petit TP, ça vous dit? ====
 +
 +Créez donc un nouveau répertoire Quelque part dans votre arborescence. Placez-y les fichiers adéquat, par exemple comme ceci:
 +
 +<​code>​
 +/ +-- home/
 +      +-- tux/
 +          +-- tuto_python/​
 +              +-- figures/
 +                  +-- __init__.py
 +                  +-- cerles.py
 +</​code>​
 +
 +Le contenu du fichier cercles.py:
 +
 +<​code>​
 +#​!/​usr/​bin/​python
 +# -*- coding: utf8 -*-
 +
 +
 +class Cercle():
 +    """​
 +    Définit un cercle de rayon R
 +
 +    EXEMPLE
 +    monCercle = Cercle(2)
 +    """​
 +    R = 0
 +
 +    def __init__(self,​ monRayon):
 +        self.R = monRayon
 +
 +    def peri(self):
 +        """​
 +        Permet de calculer le périmètre
 +        """​
 +        P = 2*pi*self.R
 +        return P
 +</​code>​
 +
 +Le contenu du fichier __init__.py :
 +
 +<​code>​
 +import cercles
 +</​code>​
 +
 +N'​oubliez pas d'​enregistrer le fichier. Maintenant, on va pouvoir faire quelques essais avec notre interpréteur et l'​introspection.
 +
 +Avec votre émulateur de terminal favori, placez-vous dans le répertoire tuto_python/​ puis lancez l'​interpréteur (ipython):
 +
 +<​code>​
 +import figures
 +
 +dir(figures)
 +help(figures)
 +type(figures)
 +</​code>​
 +
 +À cette étape, la class Cercle n'est pas directement accessible. Vous pouvez l'​utiliser comme ceci:
 +
 +<​code>​
 +monCercle = figures.cercles.Cercle(2)
 +</​code>​
 +
 +<​code>​
 +from figures import cercles
 +
 +dir(cercles)
 +help(cercles)
 +type(cercles)
 +</​code>​
 +
 +Pour utiliser la classe Cercle:
 +
 +<​code>​
 +monCercle = cercles.Cercle(2)
 +</​code>​
 +
 +<​code>​
 +from figures.cercles import Cercle
 +
 +dir(Cercle)
 +help(Cercle)
 +type(Cercle)
 +</​code>​
 +
 +Là, nous avons importé la classe Cercle, nous pouvons donc l'​utiliser directement:​
 +
 +<​code>​
 +monCercle = Cercle(2)
 +</​code>​
 +
 +Vous pouvez maintenant vous amuser à créer d'​autres éléments au module figures, des quadrilataires,​ des triangle, etc. Vous pouvez aussi vous entraîner en reprenant le code de l'​exemple du jeu de rôle ou même commencer à coder votre propre modèle, vous avez tous les outils nécessaires pour faire de l'​objet. À ce niveau, n'​essayez pas de faire des méthodes trop complexes.
 +
 +===== Passer à la vitesse supérieure =====
 +
 +  * [[expert:​uml|Tutoriel sur la modélisation uml]]
 +  * Bases de programmation avec python:
 +    * [[expert:​python_objet|Les bases de la programmation objet avec python]]
 +    * [[expert:​python_algo|Les bases de la programmation procédurale en python]]
 +    * [[expert:​sqlachemy|Les bases de données avec python]]
 +    * [[expert:​python_metaclass|Les metaclassses python]]
 +    * [[expert:​python_os|Intéraction entre python et le système]]
 +    * [[expert:​python_fabric|La bibliothèque fabric]]
 +    * [[expert:​python_virtualenv|Les environnements virtuels python]]
 +    * [[expert:​python_cherrypy|Introduction aux frameworks web avec cherrypy]]
expert/python_objet.txt · Dernière modification: 2018/11/17 13:53 (modification externe)