devstory

Héritage et polymorphisme en Python

  1. Introduction
  2. L'héritage dans Python
  3. La méthode de substitution
  4. La méthode abstraite
  5. L'héritage multiple
  6. La fonction issubclass et isinstance
  7. Le polymorphisme avec fonction

1. Introduction

L'héritage et le polymorphisme - ce sont des concepts crucials dans Python. Il est obligatoire de les comprendre si vous voulez apprendre Python.
Avant d'apprendre de "L'héritage Python", assurez- vous que vous comprenez le concept "La classe et l'objet", si non, suivez le lien suivant afin de les apprendre:
Ce document est basé sur:
  • Python 3.x

2. L'héritage dans Python

Python vous permet de créer une classe étendue d'une simple classe ou de multiple classes. Cette classe est appelée une classe dérivée (Derived class), ou simplement une sous classe.

La sous classe hérite des attributs (attribute), des méthodes et des autres membres de la classe mère. Elle peut également outrepasser (override) les méthodes de la classe mère. Si la sous classe ne définit pas son propre constructeur, elle va hériter la contructeur de la classe mère.
Contrairement aux Java, CSharp et à d' autre langages, Python supporte l'héritage multiple. Une classe peut être étendue (extends) d'une ou plusieurs classes mères.
Nous avons besoin de quelques classes qui participent dans des exemples.
  • Animal: La class simule un animal.
  • Duck: La sous class de l' Animal.
  • Cat: La sous class de l' Animal.
  • Mouse: La sous class de l' Animal.
En Python, la méthode de constructeur (constructor) de la classe utilise pour créer un objet (instance), et rattacher une valeur aux attributs (attribute).
La méthode de constructeur (constructor) des sous classes appelle toujours le constructeur de la classe mère pour initialiser la valeurs pour les attributs dans la classe mère, et puis elle va attribuer des valeurs pour ses attributs.
Exemple:
animal.py
class Animal :  

    # Constructor
    def __init__(self, name):
        
        # La classe Animal a un attribut (attribute): 'name'.
        self.name= name 
    
    # La méthode (method):
    def showInfo(self):
        print ("I'm " + self.name)
        
    # La méthode (method):
    def move(self):
        print ("moving ...")
Cat est la classe qui hérite de l' Animal, elle possède également ses attributs (attribute).
cat.py
from animal import Animal       
        
# La classe Cat est étendue (extends) de la classe Animal.
class Cat (Animal): 
    
    def __init__(self, name, age, height):
        # Appelez au constructeur de la classe mère (Animal)
        # pour attribuer la valeur au attribut 'name' de la classe mère.
        super().__init__(name)
        
        self.age = age 
        self.height = height
    
    # Remplacez (override) la méthode ayant le même nom de la classe mère.
    def showInfo(self):
        
        print ("I'm " + self.name)
        print (" age " + str(self.age))
        print (" height " + str(self.height))
catTest.py
from cat import Cat


tom = Cat("Tom", 3, 20)

print ("Call move() method")

tom.move()

print ("\n")
print ("Call showInfo() method")

tom.showInfo()
Exécution le module catTest:
Call move() method
moving ...

Call showInfo() method
I'm Tom
 age 3
 height 20
Qu'est-ce qui se passe quand vous créez un objet de constructeur (constructor)?. Comment appelez- vous le contructeur de la classe mère? Observez l'exemple ci- dessous:
Avec l'illustration dessus vous trouvez que, le constructeur (constructor) de la classe mère est appelé dans le constructeur de la sous classe, elle va attribuer des valeurs pour les attributs (attribute) de la classe mère, ensuite les attributs de la sous classe.

3. La méthode de substitution

Par défaut la sous classe hérite les méthodes de la classe mère, mais des classes mères peuvent outrepasser (override) la méthode de la classe mère.
mouse.py
from animal import Animal       
        
# La classe Mouse est étendue (extends) de la classe Animal.
class Mouse (Animal): 
    
    def __init__(self, name, age, height):
        # Appelez au Constructeur de la classe mère (Animal)
        # pour attribuer de la valeur au attribut 'name' de la classe mère.
        super().__init__(name)
        
        self.age = age 
        self.height = height
    
    # Remplacez (override) la méthode ayant le même nom de la classe mère.
    def showInfo(self):
        # Appelez la méthode de la classe mère.
        super().showInfo()
        print (" age " + str(self.age))
        print (" height " + str(self.height))
    
    # Remplacez (override) la méthode ayant le même nom de la classe mère.
    def move(self):
        print ("Mouse moving ...")
Test
mouseTest.py
from mouse import Mouse


jerry = Mouse("Jerry", 3, 5)

print ("Call move() method")

jerry.move()

print ("\n")
print ("Call showInfo() method")

jerry.showInfo()
Output:
Call move() method
Mouse moving ...

Call showInfo() method
I'm Jerry
 age 3
 height 5

4. La méthode abstraite

Le concept de une méthode abstraite (abstract method) ou une classe abstraite (abstract class) sont définis dans des langages comme Java, C#. Mais ils ne sont pas clairement définis en Python. Mais nous pouvons les définir.
Une classe est appelée abstraite (abstract) définit des méthodes abstraites et la sous classe doit outrepasser (override) ces méthodes si vous voulez les utilier. Les méthodes abstraites jètent toujours l'exception NotImplementedError.
abstractExample.py
# Une classe abstraite (Abstract class).
class AbstractDocument :
    
    def __init__(self, name):
        
        self.name = name
        
    # Une méthode ne peut pas être utilisée car elle lança toujours une erreur.
    def show(self):
        raise NotImplementedError("Subclass must implement abstract method")    
    
    

class PDF(AbstractDocument):
    
    # Remplacez la méthode de la classe mère
    def show(self):
        print ("Show PDF document:", self.name)
        
        
class Word(AbstractDocument):     
    
    def show(self):
        print ("Show Word document:", self.name)

# ----------------------------------------------------------
documents = [ PDF("Python tutorial"),
              Word("Java IO Tutorial"),
              PDF("Python Date & Time Tutorial") ]     


for doc in documents :
    
    doc.show()
Output:
Show PDF document: Python tutorial
Show Word document: Java IO Tutorial
Show PDF document: Python Date & Time Tutorial
L'exemple dessous décrit le polymorphisme (Polymorphism) en Python. Un objet Document (document) peut être représenté sous différentes formes (PDF, Word, Excel, ...).
Un autre exemple illustre le polumorphisme: Quand je parle d'un asiatique, il n'est assez abstrait, il peut être Japonais, Vietnamien ou Indien. Mais il y a quelques caractéristiques des asiatiques.

5. L'héritage multiple

Python permet de l'héritage multiple, cela signifie que vous pouvez créer une classe étendue (extends) depuis deux ou plusieurs classes. Les classes mères peuvent avoir les même attributs (attribute), ou les même méthodes,.... La sous classe va prioriser des attributs, des méthodes, ... de la première classe dans la listede l'héritage.
multipleInheritanceExample.py
class Horse: 
    maxHeight = 200; # centimeter
    
    def __init__(self, name, horsehair):
        self.name = name
        self.horsehair = horsehair 

    def run(self):
        print ("Horse run")   
     
    def showName(self):
        print ("Name: (House's method): ", self.name)   
        
    def showInfo(self):
        print ("Horse Info")   

class Donkey: 
    def __init__(self, name, weight):        
        self.name = name
        self.weight = weight   
        
    def run(self):
        print ("Donkey run")     
        
    def showName(self):        
        print ("Name: (Donkey's method): ", self.name)   

    def showInfo(self):
        print ("Donkey Info")               
  
# La classe Mule hérite de la classe Horse et Donkey.
class Mule(Horse, Donkey): 
    def __init__(self, name, hair, weight): 
        Horse.__init__(self, name, hair)  
        Donkey.__init__(self, name, weight) 
    
    def run(self):   
        print ("Mule run")   

    def showInfo(self):
        print ("-- Call Mule.showInfo: --")
        Horse.showInfo(self)
        Donkey.showInfo(self) 
# ---- Test ------------------------------------
# La variable 'maxHeight', a hérité de la classe Horse.
print ("Max height ", Mule.maxHeight)

mule = Mule("Mule", 20, 1000) 
mule.run() 
mule.showName()  
mule.showInfo()
Output:
Max height  200
Mule run
Name: (House's method): Mule
-- Call Mule.showInfo: --
Horse Info
Donkey Info
La méthode mro()
La méthode mro() vous aide de voir la liste des classes mères d'une certaine classe. Observez l'exemple ci- dessous:
mroExample.py
class X: pass
class Y: pass
class Z: pass

class A(X,Y): pass
class B(Y,Z): pass

class M(B,A,Z): pass

# Output:
# [<class '__main__.M'>, <class '__main__.B'>,
# <class '__main__.A'>, <class '__main__.X'>,
# <class '__main__.Y'>, <class '__main__.Z'>,
# <class 'object'>]
print(M.mro())
Remarque: En Python, l'instruction pass (pass statement) est comme une instruction null (ou vite), elle ne fait rien, si la classe ou la méthode ne comprend pas de contenu, vous avez besoin au moins une instruction, utilisez l'instruction pass.

6. La fonction issubclass et isinstance

Python a 2 fonctions utiles:
  • isinstance
  • issubclass
isinstance
La fonction isinstance vous aide de vérifier si quelque chose est un objet d'une certaine classe ou pas.
issubclass
La fonction issubclass vérifie si cette classe est la sous classe d'une autre classe ou pas.
isinstancesubclass.py
class A: pass
class B(A): pass 
# True
print ("isinstance('abc', object): ",isinstance('abc', object))
# True
print ("isinstance(123, object): ",isinstance(123, object))

b = B()
a = A()

# True
print ("isinstance(b, A): ", isinstance(b, A) )
print ("isinstance(b, B): ", isinstance(b, B) )

# False
print ("isinstance(a, B): ", isinstance(a, B) )

# B is subclass of A? ==> True
print ("issubclass(B, A): ", issubclass(B, A) )

# A is subclass of B? ==> False
print ("issubclass(A, B): ", issubclass(A, B) )
Output:
isinstance('abc', object): True
isinstance(123, object): True
b = B()
a = A()
isinstance(b, A): True
isinstance(b, B): True
isinstance(a, B): False
isinstance(B, A): True
isinstance(A, B): False

7. Le polymorphisme avec fonction

Ici je crée 2 classes English et French. Toutes les deux classes ont la méthode greeting(). Toutes les deux créent les salutations différentes. Créez 2 objets correspondants de lesdites classes dessus et appelez les actions de ces deux objets dans la même fonction (La fonction intro)
people.py
class English:
    def greeting(self):      
        print ("Hello")
      
class French:
    def greeting(self):
        print ("Bonjour")

def intro(language):  
    language.greeting()
  
flora  = English()
aalase = French() 
intro(flora)
intro(aalase)
Exécutez l'exemple:
Hello
Bonjour