Python orienté objet


Python est depuis le début un langage orienté objet. De ce fait, il est 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é aux langages de programmation orientés objet auparavant, vous devrez peut-être d'abord comprendre certaines fonctionnalités de base des langages orientés objet et former un concept de base orienté objet dans votre esprit, ce qui vous aidera à apprendre facilement la programmation orientée objet en Python.

Ensuite, comprenons brièvement quelques caractéristiques de base de l'orientation objet.


Introduction à la technologie orientée objet

  • Classe (Class) : est utilisé pour décrire une collection d'objets avec les mêmes propriétés et méthodes. Il définit les propriétés et méthodes communes à chaque objet de la collection. Les objets sont des instances de classes.

  • Variables de classe : Les variables de classe sont communes dans tout l'objet instancié. Les variables de classe sont définies dans la classe et en dehors du corps de la fonction. Les variables de classe ne sont généralement pas utilisées comme variables d'instance.

  • Données membres : Les variables de classe ou les variables d'instance sont utilisées pour traiter les données liées à la classe et à ses objets d'instance.

  • Réécriture de méthode : Si la méthode héritée de la classe parent ne peut pas répondre aux besoins de la sous-classe, elle peut être réécrite. Ce processus est appelé remplacement de méthode). , également connu sous le nom de remplacement de méthode.

  • Variables d'instance : Les variables définies dans les méthodes n'agissent que sur la classe de l'instance actuelle.

  • Héritage : C'est-à-dire qu'une classe dérivée hérite des champs et des méthodes de la classe de base. L'héritage permet également à un objet d'une classe dérivée d'être traité comme un objet de classe de base. Par exemple, il existe une telle conception : un objet de type Dog est dérivé de la classe Animal, qui simule la relation "est-un" (par exemple, Dog est un animal).

  • Instanciation : Créer une instance d'une classe, un objet spécifique de la classe.

  • Méthode : Fonction définie dans la classe.

  • Objet : Une instance d'une structure de données définie par une classe. Les objets incluent deux données membres (variables de classe et variables d'instance) et des méthodes.


Créer une classe

Utilisez l'instruction class pour créer une nouvelle classe, suivie de class est le nom de la classe et se termine par deux points, comme dans l'exemple suivant :

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

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

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

Instance

Ce qui suit est un exemple simple de classe Python :

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

class Employee:
   '所有员工的基类'
   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, sa valeur sera dans cette classe Partagée entre toutes les instances. Vous pouvez y accéder en utilisant Employee.empCount dans la classe interne ou la classe externe.

  • La première méthode __init__() est une méthode spéciale, appelée constructeur ou méthode d'initialisation de la classe, qui est appelée lors de la création d'une instance de cette classe. La méthode


Créer un objet instance

Pour créer une instance d'une classe, vous utilisez le nom de la classe et acceptez les arguments via la méthode __init__.

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

Accès aux propriétés

Vous pouvez utiliser le point (.) pour accéder aux propriétés d'un objet. Utilisez le nom de classe suivant pour accéder aux variables de classe :

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

Instance complète :

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

class Employee:
   '所有员工的基类'
   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

"创建 Employee 类的第一个对象"
emp1 = Employee("Zara", 2000)
"创建 Employee 类的第二个对象"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

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

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

Vous pouvez ajouter, supprimez et modifiez les attributs de la classe, comme indiqué ci-dessous :

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

Vous pouvez également utiliser la fonction suivante pour accéder aux attributs :

  • getattr(obj, name[ , par défaut]) : accédez à la propriété de l'objet.

  • hasattr(obj,name) : Vérifiez si un attribut existe.

  • setattr(obj,name,value) : définit un attribut. Si la propriété n'existe pas, une nouvelle propriété est créée.

  • delattr(obj, name) : Supprimer les attributs.

hasattr(emp1, 'age')    # 如果存在 'age' 属性返回 True。
getattr(emp1, 'age')    # 返回 'age' 属性的值
setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8
delattr(empl, 'age')    # 删除属性 'age'

Attributs de classe intégrés Python

  • __dict__ : attributs de la classe (contient un dictionnaire composé des attributs de données de la classe)

  • __doc__ : Chaîne de documentation de la classe

  • __name__ : Nom de la classe

  • __module__ : Définition de la classe Le module dans lequel elle se trouve (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__ : toutes les classes parents de la classe Les éléments constitutifs (contenant un tuple composé de toutes les classes parents)

L'exemple d'appel des attributs de classe intégrés de Python est le suivant suit :

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

class Employee:
   '所有员工的基类'
   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__

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

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'objet python (garbage collection)

Comme le langage Java, Python utilise une technologie simple appelée comptage de références pour suivre les objets en mémoire.

En interne, Python enregistre le nombre de références de chaque objet utilisé.


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

Lorsqu'un objet est créé, un décompte de références est créé Lorsque l'objet n'est plus nécessaire, Autrement dit, lorsque le nombre de références de cet objet devient 0, il est récupéré. Mais le recyclage n’est pas « immédiat » ; L'interpréteur récupérera l'espace mémoire occupé par les objets indésirables 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 récupération de place cible non seulement les objets avec un nombre de références de 0, mais peut également gérer les références circulaires. Une référence circulaire se produit lorsque deux objets se réfèrent l’un à l’autre, mais qu’aucune autre variable ne s’y réfère. Dans ce cas, le comptage de références seul ne suffit pas. Le garbage collector de Python est en fait un compteur de références et un garbage collector cyclique. En plus du comptage de références, le garbage collector examine également les objets qui ont reçu une grande quantité d'objets (et ceux qui n'ont pas été détruits par le comptage de références). Dans ce cas, l'interpréteur fera une pause et tentera de nettoyer toutes les boucles non référencées.

Instance

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

#!/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, "销毁"

pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # 打印对象的id
del pt1
del pt2
del pt3

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

3083401324 3083401324 3083401324
Point 销毁

Remarque : Habituellement, vous devez définir une classe dans un fichier séparé,

Héritage de classe

Object- orienté L'un des principaux avantages apportés par la programmation est la réutilisation du code, et l'un des moyens d'y parvenir consiste à utiliser le mécanisme d'héritage. L'héritage peut être complètement compris comme la relation de type et de sous-type entre les classes.

Choix à noter : Syntaxe d'héritage classe Nom de classe dérivé (Nom de classe de base) : //... Le nom de la classe de base est écrit entre parenthèses, et le la classe de base est Elle est spécifiée dans le tuple lorsque la classe est définie.

Quelques fonctionnalités de l'héritage en python :

  • 1 : En héritage, la construction de la classe de base (méthode __init__()) ne sera pas automatiquement appelée, elle a besoin Appelez-le spécifiquement dans le constructeur de sa classe dérivée.

  • 2 : Lors de l'appel de la méthode de la classe de base, vous devez ajouter le préfixe du nom de classe de la classe de base et vous devez apporter la variable de paramètre self. Contrairement à l'appel de fonctions ordinaires dans une classe, vous n'avez pas besoin d'apporter le paramètre self

  • 3 : Python recherche toujours d'abord la méthode du type correspondant, s'il ne trouve pas la méthode correspondante méthode dans la méthode de classe dérivée, elle commence à rechercher un par un dans la classe de base. (Recherchez d'abord la méthode appelante dans cette classe, puis recherchez-la dans la classe de base si vous ne la trouvez pas).

Si plus d'une classe est répertoriée dans le tuple d'héritage, alors cela est appelé "héritage multiple".

Syntaxe :

Déclaration des classes dérivées, similaires à leurs classes parents, avec une liste de classes de base héritées suivant le nom de la classe, comme suit :

class SubClassName (ParentClass1[, ParentClass2, ...]):
   'Optional class documentation string'
   class_suite

Instance :

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

class Parent:        # 定义父类
   parentAttr = 100
   def __init__(self):
      print "调用父类构造函数"

   def parentMethod(self):
      print '调用父类方法'

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print "父类属性 :", Parent.parentAttr

class Child(Parent): # 定义子类
   def __init__(self):
      print "调用子类构造方法"

   def childMethod(self):
      print '调用子类方法 child method'

c = Child()          # 实例化子类
c.childMethod()      # 调用子类的方法
c.parentMethod()     # 调用父类方法
c.setAttr(200)       # 再次调用父类的方法
c.getAttr()          # 再次调用父类的方法

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

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

Vous pouvez hériter de plusieurs classes

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

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

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

Vous pouvez utiliser issubclass() ou isinstance( ) méthode à tester.

  • issubclass() - Fonction booléenne pour déterminer si une classe est une sous-classe ou descendante d'une autre classe, syntaxe : issubclass(sub,sup)

  • isinstance(obj, Class) La fonction booléenne renvoie vrai si obj est un objet instance de la classe Class ou un objet instance d'une sous-classe Class.


Réécriture de méthode

Si la fonction de votre méthode de classe parent ne peut pas répondre à vos besoins, vous pouvez remplacer la méthode de votre classe parent dans la sous-classe :

Exemple :

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

class Parent:        # 定义父类
   def myMethod(self):
      print '调用父类方法'

class Child(Parent): # 定义子类
   def myMethod(self):
      print '调用子类方法'

c = Child()          # 子类实例
c.myMethod()         # 子类调用重写方法

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

调用子类方法

Méthode de surcharge de base

Le tableau suivant répertorie quelques-unes common Vous pouvez remplacer la fonction dans votre propre classe :

< td>3
Numéro de série Méthodes, descriptions et appels simples
1
序号方法, 描述 & 简单的调用
1__init__ ( self [,args...] )
构造函数
简单的调用方法: obj = className(args)
2__del__( self )
析构方法, 删除一个对象
简单的调用方法 : dell obj
3__repr__( self )
转化为供解释器读取的形式
简单的调用方法 : repr(obj)
4__str__( self )
用于将值转化为适于人阅读的形式
简单的调用方法 : str(obj)
5__cmp__ ( self, x )
对象比较
简单的调用方法 : cmp(obj, x)
__init__ ( self [,args...] )<🎜>< br />Constructeur
Méthode d'appel simple : obj = className(args)
2< 🎜>__del__ ( self )<🎜>
Méthode destructeur, supprimer un objet
Méthode d'appel simple : dell obj
<🎜>__repr__( self )<🎜>
Convertir en un formulaire lu par l'interpréteur
Méthode d'appel simple : repr(obj)
4<🎜>__str__( self )<🎜>
Utilisé pour convertir les valeurs en un formulaire 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 d'opérateurs

Python prend également en charge la surcharge d'opérateurs. Les exemples sont les suivants :

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

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

Vector(7,8)

Attribut de classe Attributs privés de la classe

__private_attrs

avec la méthode : commençant par deux traits de soulignement, déclare que l'attribut est privé et ne peut être utilisé ni accessible directement en dehors de la classe. Lorsqu'il est utilisé dans une méthode à l'intérieur d'une classe self.__private_attrs.

Méthodes de classe

Au sein de la classe, vous pouvez utiliser le mot-clé def pour définir une méthode pour la classe. Différente de la définition générale de la fonction, la méthode de classe doit contenir le paramètre self, qui est. le premier paramètre.

Méthodes privées de la classe

__private_method : Commençant par deux traits de soulignement, la méthode est déclarée comme méthode privée et ne peut pas être appelée en dehors de la classe. Appeler self.__private_methods

instance

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

class JustCounter:
	__secretCount = 0  # 私有变量
	publicCount = 0    # 公开变量

	def count(self):
		self.__secretCount += 1
		self.publicCount += 1
		print self.__secretCount

counter = JustCounter()
counter.count()
counter.count()
print counter.publicCount
print counter.__secretCount  # 报错,实例不能访问私有变量

Python à l'intérieur d'une classe en modifiant 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 n'autorise pas l'instanciation Les classes accèdent aux données privées, mais vous pouvez utiliser object._className__attrName pour accéder aux attributs. Remplacez la dernière ligne du code ci-dessus par le code suivant :

.........................
print counter._JustCounter__secretCount

Exécutez le code ci-dessus et l'exécution. le résultat est le suivant :

1
2
2
2