Python orienté objet

Python est un langage orienté objet depuis sa conception. Pour cette raison, il est très facile de créer des classes et des objets en Python. Dans ce chapitre, nous présenterons en détail la programmation orientée objet en Python.

Si vous n'avez jamais été exposé à des langages de programmation orientés objet auparavant, vous devrez peut-être d'abord comprendre certaines caractéristiques de base des langages orientés objet et vous former un concept de base de l'orienté objet dans votre esprit, ce qui vous aidera à apprendre plus facilement la programmation orientée objet en Python.

Voyons maintenant brièvement quelques caractéristiques de base de l'orienté objet.


Introduction à la technologie orientée objet

  • Classe :Utilisée pour décrire un ensemble d'objets ayant les mêmes attributs et méthodes. Elle définit les attributs et les méthodes communs à chaque objet de l'ensemble. Les objets sont des instances de classes.
  • Variable de classe :Les variables de classe sont partagées entre tous les objets instanciés. Les variables de classe sont définies dans la classe et en dehors de tout corps de fonction. Les variables de classe ne sont généralement pas utilisées comme variables d'instance.
  • Membres de données :Variables de classe ou variables d'instance, utilisées pour traiter les données liées à la classe et à ses objets d'instance.
  • Redéfinition de méthode :Si une méthode héritée de la classe parente ne peut pas répondre aux besoins de la classe enfant, elle peut être réécrite. Ce processus est appelé redéfinition de méthode.
  • Variables locales :Variables définies dans les méthodes, n'affectant que la classe de l'instance actuelle.
  • Variables d'instance :Dans la déclaration de classe, les attributs sont représentés par des variables. Ces variables sont appelées variables d'instance, déclarées à l'intérieur de la déclaration de classe mais en dehors des autres méthodes membres de la classe.
  • Héritage :C'est-à-dire qu'une classe dérivée hérite des champs et des méthodes d'une classe de base. L'héritage permet également de traiter un objet d'une classe dérivée comme un objet d'une classe de base. Par exemple, il existe une conception : un objet de type Dog dérive de la classe Animal, ce qui simule une relation « est-un » (par ex., Dog est un Animal).
  • Instanciation :Créer une instance d'une classe, l'objet concret de la classe.
  • Méthode :Une fonction définie dans une classe.
  • Objet :Une instance d'une structure de données définie par une classe. Les objets comprennent deux membres de données (variables de classe et variables d'instance) et des méthodes.

Création de classes

Utilisez l'instruction class pour créer une nouvelle classe. Après class vient le nom de la classe, et l'instruction se termine par deux points :

class ClassName:
   '类的帮助信息'   #类文档字符串
   class_suite  #类体

Les informations d'aide de la classe peuvent être consultées via ClassName.__doc__.

class_suite se compose des membres de classe, des méthodes et des attributs de données.

Exemple

Voici un exemple simple de classe Python :

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Classe de base pour tous les employés' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total employés %d" % Employee.empCount def displayEmployee(self): print "Nom : ", self.name, ", Salaire : ", self.salary
  • La variable empCount est une variable de classe dont la valeur est partagée entre toutes les instances de cette classe. Vous pouvez y accéder via Employee.empCount à l'intérieur ou à 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. Cette méthode est appelée lorsqu'une instance de la classe est créée.

  • self représente une instance de la classe. self est requis lors de la définition des méthodes de classe, bien que le paramètre correspondant n'ait pas besoin d'être passé lors de l'appel.

self représente une instance de la classe, et non la classe

Les méthodes de classe n'ont qu'une seule différence spéciale par rapport aux fonctions ordinaires - elles doivent avoir unnom du premier paramètresupplémentaire, par convention son nom est self.

class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()

Le résultat d'exécution de l'exemple ci-dessus est :

<__main__.Test instance at 0x10d066878>
__main__.Test

D'après le résultat de l'exécution, il est très clair que self représente l'instance de la classe, représentant l'adresse de l'objet courant, tandis queself.__class__pointe vers la classe.

self n'est pas un mot-clé Python. Nous pouvons le remplacer par example et il s'exécutera toujours normalement :

Exemple

class Test: def prt(example): print(example) print(example.__class__) t = Test() t.prt()

Le résultat d'exécution de l'exemple ci-dessus est :

<__main__.Test instance at 0x10d066878>
__main__.Test

Création d'objets d'instance

Lors de l'instanciation d'une classe, les autres langages de programmation utilisent généralement le mot-clé new, mais en Python ce mot-clé n'existe pas. L'instanciation de classe est similaire à un appel de fonction.

Ce qui suit utilise le nom de classe Employee pour instancier, et reçoit des paramètres via la méthode __init__.

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)

Accès aux attributs

Vous pouvez utiliser le point.pour accéder aux attributs de l'objet. Utilisez le nom de classe comme suit pour accéder aux variables de classe :

emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

Exemple complet:

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Classe de base pour tous les employés' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total employés %d" % Employee.empCount def displayEmployee(self): print "Nom : ", self.name, ", Salaire : ", self.salary "Créer le premier objet de la classe Employee" emp1 = Employee("Zara", 2000) "Créez le deuxième objet de la classe Employee" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount

La sortie de l'exécution du code ci-dessus est la suivante :

Name :  Zara ,Salary:  2000
Name :  Manni ,Salary:  5000
Total Employee 2

Vous pouvez ajouter, supprimer et modifier les attributs de classe comme indiqué ci-dessous :

emp1.age = 7  # 添加一个 'age' 属性
emp1.age = 8  # 修改 'age' 属性
del emp1.age  # 删除 'age' 属性

Vous pouvez également utiliser les fonctions suivantes pour accéder aux attributs :

  • getattr(obj, name[, default]) : Accéder à l'attribut de l'objet.
  • hasattr(obj,name) : Vérifier si un attribut existe.
  • setattr(obj,name,value) : Définir un attribut. Si l'attribut n'existe pas, un nouvel attribut est créé.
  • delattr(obj, name) : Supprimer l'attribut.
hasattr(emp1, 'age') # Renvoie True si l'attribut 'age' existe. getattr(emp1, 'age') # Renvoie la valeur de l'attribut 'age' setattr(emp1, 'age', 8) # Ajoute l'attribut 'age' avec la valeur 8 delattr(emp1, 'age') # Supprime l'attribut 'age'

Attributs de classe intégrés de Python

  • __dict__ : Les attributs de la classe (contenant un dictionnaire composé des attributs de données de la classe)
  • __doc__ : La chaîne de documentation de la classe
  • __name__: Nom de la classe
  • __module__: Le module dans lequel la classe est définie (le nom complet de la classe est '__main__.className' ; si la classe se trouve dans un module importé mymod, alors className.__module__ est égal à mymod)
  • __bases__ : Les éléments constituant toutes les classes parentes de la classe (contenant un tuple composé de toutes les classes parentes)

Ce qui suit est un exemple d'appel des attributs de classe intégrés de Python :

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: 'Classe de base pour tous les employés' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total employés %d" % Employee.empCount def displayEmployee(self): print "Nom : ", self.name, ", Salaire : ", 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__

La sortie de l'exécution du code ci-dessus est la suivante :

Employee.__doc__: 所有员工的基类
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {'__module__': '__main__', 'displayCount': <function displayCount at 0x10a939c80>, 'empCount': 0, 'displayEmployee': <function displayEmployee at 0x10a93caa0>, '__doc__': '\xe6\x89\x80\xe6\x9c\x89\xe5\x91\x98\xe5\xb7\xa5\xe7\x9a\x84\xe5\x9f\xba\xe7\xb1\xbb', '__init__': <function __init__ at 0x10a939578>}

Destruction d'objets en Python (ramasse-miettes)

Python utilise la technique simple du comptage de références pour suivre et récupérer les déchets.

En interne, Python enregistre le nombre de références existant pour tous les objets utilisés.

Une variable de suivi interne, appelée compteur de références.

Lorsqu'un objet est créé, un compteur de références est créé. Lorsque cet objet n'est plus nécessaire, c'est-à-dire lorsque le nombre de références de l'objet devient 0, il est collecté par le ramasse-miettes. Toutefois, la collecte n'est pas « immédiate » ; l'interpréteur récupère l'espace mémoire occupé par l'objet indésirable au moment approprié.

a = 40      # 创建对象  <40>
b = a       # 增加引用, <40> 的计数
c = [b]     # 增加引用.  <40> 的计数

del a       # 减少引用 <40> 的计数
b = 100     # 减少引用 <40> 的计数
c[0] = -1   # 减少引用 <40> 的计数

Le mécanisme de ramasse-miettes ne cible pas seulement les objets dont le compteur de références est à 0, il peut aussi gérer les références circulaires. Les références circulaires désignent deux objets qui se référencent mutuellement, mais qu'aucune autre variable ne référence. Dans ce cas, se fier uniquement au comptage de références est insuffisant. Le ramasse-miettes de Python est en réalité un compteur de références et un collecteur de déchets circulaires. En complément du comptage de références, le ramasse-miettes surveille aussi les objets dont l'allocation totale est importante (c'est-à-dire ceux qui ne sont pas détruits par le comptage de références). Dans de tels cas, l'interpréteur se met en pause et tente de nettoyer tous les cycles non référencés.

Exemple

Le destructeur __del__ est appelé lorsque l'objet est détruit. Lorsque l'objet n'est plus utilisé, la méthode __del__ s'exécute :

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- 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) # Afficher l'id de l'objet del pt1 del pt2 del pt3

Le résultat d'exécution de l'exemple ci-dessus est le suivant :

3083401324 3083401324 3083401324
Point 销毁

Remarque :Généralement, vous devez définir une classe dans un fichier séparé,

Héritage de classe

L'un des principaux avantages de la programmation orientée objet est la réutilisation du code, et l'un des moyens d'atteindre cette réutilisation est le mécanisme d'héritage.

La nouvelle classe créée par héritage est appelée lasous-classeouclasse dérivée, et la classe dont on hérite est appelée laclasse de base、classe parenteousuper-classe。

Syntaxe de l'héritage

class 派生类名(基类名)
    ...

Quelques caractéristiques de l'héritage en Python :

  • 1. Si le constructeur de la classe parente est nécessaire dans la sous-classe, vous devez appeler explicitement le constructeur de la classe parente, ou ne pas redéfinir le constructeur de la classe parente. Pour plus de détails, voir :Explication de l'héritage du constructeur de la classe parente par une sous-classe Python。
  • 2. Lorsque vous appelez une méthode de la classe de base, vous devez la préfixer avec le nom de la classe de base et inclure la variable de paramètre self. La différence est que lorsque vous appelez des fonctions ordinaires au sein d'une classe, vous n'avez pas besoin d'inclure le paramètre self.
  • 3. Python recherche toujours d'abord le type de méthode correspondant. S'il ne trouve pas la méthode correspondante dans la classe dérivée, il cherche ensuite dans les classes de base une par une. (Il cherche d'abord la méthode appelée dans la classe actuelle, et ne va dans la classe de base que si elle n'est pas trouvée.)

Si plus d'une classe est listée dans le tuple d'héritage, on parle d'« héritage multiple ».

Syntaxe :

La déclaration d'une classe dérivée est similaire à celle de sa classe parente. La liste des classes de base héritées suit le nom de la classe, comme indiqué ci-dessous :

class SubClassName (ParentClass1[, ParentClass2, ...]):
    ...

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # Définir la classe parente parentAttr = 100 def __init__(self): print "Appeler le constructeur de la classe parente" def parentMethod(self): print 'Appeler une méthode de la classe parente' def setAttr(self, attr): Parent.parentAttr = attr def getAttr(self): print "Attribut de la classe parente :", Parent.parentAttr class Child(Parent): # Définir la sous-classe def __init__(self): print "Appeler le constructeur de la sous-classe" def childMethod(self): print 'Appeler une méthode de la sous-classe' c = Child() # Instancier la sous-classe c.childMethod() # Appeler une méthode de la sous-classe c.parentMethod() # Appeler une méthode de la classe parente c.setAttr(200) # Appeler à nouveau une méthode de la classe parente - définir la valeur de l'attribut c.getAttr() # Appeler à nouveau une méthode de la classe parente - obtenir la valeur de l'attribut

La sortie du code ci-dessus est la suivante :

调用子类构造方法
调用子类方法
调用父类方法
父类属性 : 200

Vous pouvez hériter de plusieurs classes

class A:        # 定义类 A
.....

class B:         # 定义类 B
.....

class C(A, B):   # 继承类 A 和 B
.....

Vous pouvez utiliser les méthodes issubclass() ou isinstance() pour vérifier.

  • issubclass() - Une fonction booléenne qui détermine si une classe est une sous-classe ou une descendante d'une autre classe. Syntaxe : issubclass(sub, sup)
  • isinstance(obj, Class) Une fonction booléenne qui renvoie true si obj est un objet instance de la classe Class ou un objet instance d'une sous-classe de Class.

Redéfinition de méthode

Si la fonctionnalité de la méthode de votre classe parente ne peut pas répondre à vos besoins, vous pouvez redéfinir la méthode de la classe parente dans la sous-classe :

Exemple :

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class Parent: # Définir la classe parente def myMethod(self): print 'Appeler une méthode de la classe parente' class Child(Parent): # Définir la sous-classe def myMethod(self): print 'Appeler une méthode de la sous-classe' c = Child() # Instance de la sous-classe c.myMethod() # La sous-classe appelle la méthode redéfinie

Après avoir exécuté le code ci-dessus, la sortie est la suivante :

Calling subclass methods

Méthodes de surcharge de base

Le tableau suivant répertorie certaines fonctions courantes que vous pouvez redéfinir dans vos propres classes :

Non.Méthode, Description et Appel simple
1__init__ ( self [,args...] )
Constructeur
Méthode d'appel simple :obj = className(args)
2__del__( self )
Méthode destructeur, supprime un objet
Méthode d'appel simple :del obj
3__repr__( self )
Convertir en une forme lisible par l'interpréteur
Méthode d'appel simple :repr(obj)
4__str__( self )
Utilisé pour convertir une valeur en une forme lisible par l'homme
Méthode d'appel simple :str(obj)
5__cmp__ ( self, x )
Comparaison d'objets
Méthode d'appel simple :cmp(obj, x)

Surcharge des opérateurs

Python prend également en charge la surcharge des opérateurs, comme le montre l'exemple ci-dessous :

Exemple

#!/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

La sortie du code ci-dessus est la suivante :

Vector(7,8)

Attributs et méthodes de classe

Attributs privés d'une classe

__private_attrs: Le fait de commencer par deux underscores déclare l'attribut comme privé, qui ne peut être ni utilisé ni directement accessible en dehors de la classe. Lorsqu'il est utilisé dans des méthodes à l'intérieur de la classe,self.__private_attrs。

Méthodes d'une classe

À l'intérieur de la classe, utilisez le mot-clédefpour définir une méthode pour la classe. Contrairement aux définitions de fonctions ordinaires, une méthode d'une classe doit inclure le paramètre self comme premier paramètre.

Méthodes privées d'une classe

__private_method: Le fait de commencer par deux underscores déclare la méthode comme privée et elle ne peut pas être appelée en dehors de la classe. Pour l'appeler à l'intérieur de la classe,self.__private_methods

Exemple

#!/usr/bin/python # -*- coding: UTF-8 -*- class JustCounter: __secretCount = 0 # Variable privée publicCount = 0 # Variable publique def count(self): self.__secretCount += 1 self.publicCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.publicCount print counter.__secretCount # Erreur, une instance ne peut pas accéder à une variable privée

Python modifie le nom pour inclure le nom de la classe :

1
2
2
Traceback (most recent call last):
  File "test.py", line 17, in <module>
    print counter.__secretCount  # 报错,实例不能访问私有变量
AttributeError: JustCounter instance has no attribute '__secretCount'

Python ne permet pas aux instances de classe d'accéder aux données privées, mais vous pouvez utiliserobject._className__attrName( object_name._class_name__private_attribute_name) pour accéder à l'attribut. Reportez-vous à l'exemple suivant :

#!/usr/bin/python
# -*- coding: UTF-8 -*-

class Example:
    __site = "www.example.com"

example = Example()
print example._Example__site

Exécutez le code ci-dessus, et le résultat est le suivant :

www.example.com

Explication du trait de soulignement simple, du double trait de soulignement et du double trait de soulignement au début et à la fin :

  • __foo__: Définit des méthodes spéciales, généralement des noms définis par le système, tels que__init__()et ainsi de suite.

  • _foo: Une variable commençant par un seul trait de soulignement représente une variable de type protégé, c'est-à-dire que le type protégé n'est accessible que par lui-même et ses sous-classes, et ne peut pas être utilisé pourfrom module import *

  • __foo: Les doubles traits de soulignement indiquent une variable de type privé, qui n'est accessible que par la classe elle-même.

Autres extensions