Python - Orienté Objet
Page PrécédentePage Suivante
Python est un langage orienté objet depuis qu'il existe. Pour cette raison, la création et l'utilisation de classes et d'objets sont carrément faciles. Ce chapitre vous aide à devenir un expert dans l'utilisation de la prise en charge de la programmation orientée objet de Python.
Si vous n'avez aucune expérience préalable de la programmation orientée objet (OO), vous voudrez peut-être consulter un cours d'introduction à ce sujet ou au moins un didacticiel quelconque afin de maîtriser les concepts de base.
Cependant, voici une petite introduction à la programmation orientée objet (POO) pour vous amener à la vitesse −
Aperçu de la terminologie POO
-
Classe − Un prototype défini par l'utilisateur pour un objet qui définit un ensemble d'attributs qui caractérisent tout objet de la classe. Les attributs sont des membres de données (variables de classe et variables d'instance) et des méthodes, accessibles via la notation par points.
-
Variable de classe − Une variable partagée par toutes les instances d'une classe. Les variables de classe sont définies dans une classe mais en dehors de toutes les méthodes de la classe. Les variables de classe ne sont pas utilisées aussi fréquemment que les variables d'instance.
-
Membre de données − Une variable de classe ou une variable d'instance contenant des données associées à une classe et à ses objets.
-
Surcharge de fonction − L'attribution de plus d'un comportement à une fonction particulière. L'opération effectuée varie selon les types d'objets ou d'arguments impliqués.
-
Variable d'instance − Une variable qui est définie à l'intérieur d'une méthode et qui appartient uniquement à l'instance actuelle d'une classe.
-
Héritage − Le transfert des caractéristiques d'une classe à d'autres classes qui en sont dérivées.
-
Instance − Un objet individuel d'une certaine classe. Un objet obj qui appartient à une classe Circle, par exemple, est une instance de la classe Circle.
-
Instanciation − La création d'une instance d'une classe.
-
Méthode − Un type spécial de fonction qui est défini dans une définition de classe.
-
Objet − Une instance unique d'une structure de données définie par sa classe. Un objet comprend à la fois des données membres (variables de classe et variables d'instance) et des méthodes.
-
Surcharge d'opérateur − L'attribution de plusieurs fonctions à un opérateur particulier.
Créer des cours
La classe L'instruction crée une nouvelle définition de classe. Le nom de la classe suit immédiatement le mot-clé classe suivi de deux-points comme suit −
class ClassName: 'Optional class documentation string' class_suite
-
La classe a une chaîne de documentation, accessible via ClassName.__doc__ .
-
La class_suite se compose de toutes les déclarations de composants définissant les membres de classe, les attributs de données et les fonctions.
Exemple
Voici l'exemple d'une classe Python simple −
class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary
-
La variable empCount est une variable de classe dont la valeur est partagée entre toutes les instances de cette classe. Ceci est accessible en tant que Employee.empCount de l'intérieur ou de l'extérieur de la classe.
-
La première méthode __init__() est une méthode spéciale, appelée constructeur de classe ou méthode d'initialisation que Python appelle lorsque vous créez une nouvelle instance de cette classe.
-
Vous déclarez d'autres méthodes de classe comme des fonctions normales à l'exception que le premier argument de chaque méthode est self . Python ajoute le soi argument à la liste pour vous; vous n'avez pas besoin de l'inclure lorsque vous appelez les méthodes.
Créer des objets d'instance
Pour créer des instances d'une classe, vous appelez la classe en utilisant le nom de la classe et transmettez les arguments de son __init__ méthode accepte.
"This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000)
Accéder aux attributs
Vous accédez aux attributs de l'objet à l'aide de l'opérateur point avec objet. La variable de classe serait accessible en utilisant le nom de la classe comme suit −
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
Maintenant, rassemblant tous les concepts −
Démo en direct#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "This would create first object of Employee class" emp1 = Employee("Zara", 2000) "This would create second object of Employee class" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Name : Zara ,Salary: 2000 Name : Manni ,Salary: 5000 Total Employee 2
Vous pouvez ajouter, supprimer ou modifier les attributs des classes et des objets à tout moment −
emp1.age = 7 # Add an 'age' attribute. emp1.age = 8 # Modify 'age' attribute. del emp1.age # Delete 'age' attribute.
Au lieu d'utiliser les instructions normales pour accéder aux attributs, vous pouvez utiliser les fonctions suivantes −
-
Le getattr(obj, nom[, défaut]) − pour accéder à l'attribut de l'objet.
-
Le hasattr(obj,nom) − pour vérifier si un attribut existe ou non.
-
Le setattr(obj,name,value) − pour définir un attribut. Si l'attribut n'existe pas, alors il sera créé.
-
Le delattr(obj, nom) − pour supprimer un attribut.
hasattr(emp1, 'age') # Returns true if 'age' attribute exists getattr(emp1, 'age') # Returns value of 'age' attribute setattr(emp1, 'age', 8) # Set attribute 'age' at 8 delattr(empl, 'age') # Delete attribute 'age'
Attributs de classe intégrés
Chaque classe Python continue de suivre les attributs intégrés et ils sont accessibles à l'aide de l'opérateur point comme tout autre attribut −
-
__dict__ − Dictionnaire contenant l'espace de noms de la classe.
-
__doc__ − Chaîne de documentation de classe ou aucune, si elle n'est pas définie.
-
__nom__ − Nom de classe.
-
__module__ − Nom du module dans lequel la classe est définie. Cet attribut est "__main__" en mode interactif.
-
__bases__ − Un tuple éventuellement vide contenant les classes de base, dans l'ordre de leur occurrence dans la liste des classes de base.
Pour la classe ci-dessus essayons d'accéder à tous ces attributs −
Démo en direct#!/usr/bin/python class Employee: 'Common base class for all employees' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary print "Employee.__doc__:", Employee.__doc__ print "Employee.__name__:", Employee.__name__ print "Employee.__module__:", Employee.__module__ print "Employee.__bases__:", Employee.__bases__ print "Employee.__dict__:", Employee.__dict__
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Employee.__doc__: Common base class for all employees Employee.__name__: Employee Employee.__module__: __main__ Employee.__bases__: () Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0xb7c84994>, 'empCount': 2, 'displayEmployee': <function displayEmployee at 0xb7c8441c>, '__doc__': 'Common base class for all employees', '__init__': <function __init__ at 0xb7c846bc>}
Détruire des objets (Garbage Collection)
Python supprime automatiquement les objets inutiles (types intégrés ou instances de classe) pour libérer de l'espace mémoire. Le processus par lequel Python récupère périodiquement des blocs de mémoire qui ne sont plus utilisés est appelé Garbage Collection.
Le ramasse-miettes de Python s'exécute pendant l'exécution du programme et est déclenché lorsque le nombre de références d'un objet atteint zéro. Le nombre de références d'un objet change lorsque le nombre d'alias qui pointent vers lui change.
Le nombre de références d'un objet augmente lorsqu'un nouveau nom lui est attribué ou lorsqu'il est placé dans un conteneur (liste, tuple ou dictionnaire). Le nombre de références de l'objet diminue lorsqu'il est supprimé avec del , sa référence est réaffectée ou sa référence sort de la portée. Lorsque le nombre de références d'un objet atteint zéro, Python le collecte automatiquement.
a = 40 # Create object <40> b = a # Increase ref. count of <40> c = [b] # Increase ref. count of <40> del a # Decrease ref. count of <40> b = 100 # Decrease ref. count of <40> c[0] = -1 # Decrease ref. count of <40>
Vous ne remarquerez normalement pas lorsque le ramasse-miettes détruit une instance orpheline et récupère son espace. Mais une classe peut implémenter la méthode spéciale __del__() , appelé destructeur, qui est invoqué lorsque l'instance est sur le point d'être détruite. Cette méthode peut être utilisée pour nettoyer toutes les ressources non mémoire utilisées par une instance.
Exemple
Ce destructeur __del__() imprime le nom de classe d'une instance qui est sur le point d'être détruite −
Démo en direct#!/usr/bin/python class Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "destroyed" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts del pt1 del pt2 del pt3
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
3083401324 3083401324 3083401324 Point destroyed
Remarque − Idéalement, vous devriez définir vos classes dans un fichier séparé, puis vous devriez les importer dans votre fichier de programme principal en utilisant import déclaration.
Héritage de classe
Au lieu de partir de zéro, vous pouvez créer une classe en la dérivant d'une classe préexistante en listant la classe parente entre parenthèses après le nouveau nom de classe.
La classe enfant hérite des attributs de sa classe parent et vous pouvez utiliser ces attributs comme s'ils étaient définis dans la classe enfant. Une classe enfant peut également remplacer les données membres et les méthodes du parent.
Syntaxe
Les classes dérivées sont déclarées comme leur classe parent; cependant, une liste des classes de base dont hériter est donnée après le nom de la classe −
class SubClassName (ParentClass1[, ParentClass2, ...]): 'Optional class documentation string' class_suite
Exemple
Démo en direct#!/usr/bin/python class Parent: # define parent class parentAttr = 100 def __init__(self): print "Calling parent constructor" def parentMethod(self): print 'Calling parent method' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Parent attribute :", Parent.parentAttr class Child(Parent): # define child class def __init__(self): print "Calling child constructor" def childMethod(self): print 'Calling child method' c = Child() # instance of child c.childMethod() # child calls its method c.parentMethod() # calls parent's method c.setAttr(200) # again call parent's method c.getAttr() # again call parent's method
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Calling child constructor Calling child method Calling parent method Parent attribute : 200
De la même manière, vous pouvez piloter une classe à partir de plusieurs classes parentes comme suit −
class A: # define your class A ..... class B: # define your class B ..... class C(A, B): # subclass of A and B .....
Vous pouvez utiliser les fonctions issubclass() ou isinstance() pour vérifier les relations entre deux classes et instances.
-
La issuebclass(sub, sup) la fonction booléenne renvoie vrai si la sous-classe donnée sub est bien une sous-classe de la superclasse sup .
-
L'isinstance(obj, Class) la fonction booléenne renvoie vrai si obj est une instance de la classe Class ou est une instance d'une sous-classe de Class
Remplacer les méthodes
Vous pouvez toujours remplacer vos méthodes de classe parent. L'une des raisons pour remplacer les méthodes du parent est que vous souhaitez peut-être des fonctionnalités spéciales ou différentes dans votre sous-classe.
Exemple
Démo en direct#!/usr/bin/python class Parent: # define parent class def myMethod(self): print 'Calling parent method' class Child(Parent): # define child class def myMethod(self): print 'Calling child method' c = Child() # instance of child c.myMethod() # child calls overridden method
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Calling child method
Méthodes de surcharge de base
Le tableau suivant répertorie certaines fonctionnalités génériques que vous pouvez remplacer dans vos propres classes −
Sr.No. | Méthode, description et exemple d'appel |
---|---|
1 | |
2 | |
3 | |
4 | |
5 |
Surcharger les opérateurs
Supposons que vous ayez créé une classe Vector pour représenter des vecteurs bidimensionnels, que se passe-t-il lorsque vous utilisez l'opérateur plus pour les ajouter ? Python va très probablement crier après vous.
Vous pouvez cependant définir le __add__ méthode dans votre classe pour effectuer l'addition de vecteurs, puis l'opérateur plus se comporterait comme prévu -
Exemple
Démo en direct#!/usr/bin/python class Vector: def __init__(self, a, b): self.a = a self.b = b def __str__(self): return 'Vector (%d, %d)' % (self.a, self.b) def __add__(self,other): return Vector(self.a + other.a, self.b + other.b) v1 = Vector(2,10) v2 = Vector(5,-2) print v1 + v2
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
Vector(7,8)
Masquage des données
Les attributs d'un objet peuvent ou non être visibles en dehors de la définition de classe. Vous devez nommer les attributs avec un préfixe de double trait de soulignement, et ces attributs ne sont alors pas directement visibles pour les étrangers.
Exemple
Démo en direct#!/usr/bin/python class JustCounter: __secretCount = 0 def count(self): self.__secretCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.__secretCount
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
1 2 Traceback (most recent call last): File "test.py", line 12, in <module> print counter.__secretCount AttributeError: JustCounter instance has no attribute '__secretCount'
Python protège ces membres en modifiant en interne le nom pour inclure le nom de la classe. Vous pouvez accéder à des attributs tels que object._className__attrName . Si vous remplaciez votre dernière ligne comme suit, alors cela fonctionne pour vous −
......................... print counter._JustCounter__secretCount
Lorsque le code ci-dessus est exécuté, il produit le résultat suivant −
1 2 2
Python