VaultBy ENSAMIENParrainage
Notebook

7. Programmation Orientée Objet avec Python

07-poo.ipynb

La POO est un paradigme, càd une façon de procéder pour écrire des programmes clairs et simples.
Le principe consiste à modéliser les éléments du programme comme étant des objets caractérisés par des attributs et capables d'effectuer des actions.
Ces derniers sont rangés dans des structures appelées classes.
L'objet est une instance (réalisation "concrète") de la classe.

  • Attributs :
    • Attribut de classe
    • Attribut d'instance

Exemple:

class Voiture:
    roues = 4  # Attribut de classe, commun à toutes les instances
    def __init__(self, marque, NbRouMot=2): # constructeur
        self.marque = marque  # Attribut d'instance
        self.rouesMotrice = NbRouMot
    
    def affRouMotVoit(self):
        print(f"{self.marque}, {self.roues}x{self.rouesMotrice}")
v1 = Voiture("Hyundai")
v2 = Voiture("Skoda",4)

v1.affRouMotVoit()
v2.affRouMotVoit()

Créer des sous-classes

# classe Mère ~ Super-classe (superclass) ~ Classe de base 
class Vehicule:
    """
    Classe "Vehicule" représentant un modèle générique de véhicule
    """

    def __init__(self, couleur='noire', vitesse=0, roues=4):
        self.couleur = couleur
        self.vitesse = vitesse
        self.roues = roues

    def afficher_infos(self):
        print("Couleur :", self.couleur)
        print("Vitesse :", self.vitesse)
        print("Nombre de roues :", self.roues)

  # voici une méthode "accelerer" qui modifie un attribut de l'objet
    def accelerer(self, vitesse):
        self.vitesse += vitesse

  #  méthode pour stoper le véhicule
    def stop(self):
        self.vitesse = 0
voiture_1 = Vehicule()
voiture_1.afficher_infos()
voiture_1.accelerer(60)
voiture_1.accelerer(40)
voiture_1.afficher_infos()
# Remarque: obligation de self
class A:
    def test(self):          # avec ou sans self
        print("Test Bonjour")
a = A()
a.test()
# classe Fille ~ Sous-classe (subclass) ~ Classe dérivée 
class voiture_electrique(Vehicule):
  """
  La classe voiture_electrique hérite des méthodes et des attributs
  de la classe véhicule
  """

  def __init__(self, couleur='black', vitesse=0, roues=4, autonomie=100):
    super().__init__(couleur, vitesse, roues) # super() permet d'utiliser la fonction de la classe "parent"
    self.autonomie = autonomie

  # Ré-écriture de certaines méthodes
  def accelerer(self, vitesse):
    super().accelerer(vitesse)
    self.autonomie -= 0.005 * self.vitesse

  def afficher(self):
    super().afficher_infos()
    print(f'autonomie: {self.autonomie}')
voiture_2 = voiture_electrique()
print("----------------- Au repos ----")
voiture_2.afficher()

voiture_2.accelerer(70)
print("----------------- Acceleration ----")
voiture_2.afficher()
  • Attribut Protégé :
    • Syntaxe : Précédé d'un underscore '_' après le self.
    • Accessible dans les sous-classes (classe fille),
    • Accès possible depuis l'extérieur, mais non recommandé
class Animal:
    def __init__(self, nom):
        self._nom = nom  # Attribut protégé

    def afficher_nom(self):
        print(f"Nom : {self._nom}")

class Chien(Animal):
    def aboyer(self):
        print(f"{self._nom} aboie !")  # Accessible ici
rex = Chien("Rex")
rex.aboyer()                       # chien Rex aboie !
print("Accès champ protégé depuis la classe fille : ", rex._nom)

A = Animal("Ipsw")
A.afficher_nom()
print("Accès champ protégé depuis l'exterieur : ", A._nom) # Possible, mais à éviter
  • Attribut Privé :
    • Syntaxe: Précédé de deux underscores '__' après le self.
    • Non accessible dans les sous-classes (classe fille),
    • Accès impossible depuis l'extérieur,
class Exemple:
    def __init__(self):
        self.commun = "TouteInfo"
        self.__secret = "INNER"
        
    def affSec(self):
        print("Val:",self.__secret)
e = Exemple()

print(e.commun)  # Affiche
e.affSec() # acces interne
class CmptBanc:
    def __init__(self, solde_initial):
        self._solde = solde_initial         # attribut Protégé
        self.__numero_compte = "123ABCS"    # attribut Privé

c = CmptBanc(1000)
print(c._solde)                  # Possible, mais déconseillé
print(c.__numero_compte)       # Erreur : attribut privé
  • Attribut Privé : Accès via name mangling
# déformation du nom d'attribut
# syntax : ._nonClass__nomAttribut
print(c._CmptBanc__numero_compte)    

# Python ne stocke pas cet attribut sous le nom que vous avez tapé. 
# Mais, il le renomme automatiquement en interne en lui préfixant 
# un underscore et le nom de la classe.
# name mangling pour attribut protégé:
print(c._CmptBanc_solde)      
  • Accès via des getter | setter
class CompteBancaire:
    def __init__(self, solde_initial, NumCompt):
        self._solde = solde_initial         # attribut Protégé
        self.__numero_compte = NumCompt    # attribut Privé
        
    def afficher_numero(self):
        print(self.__numero_compte)
        
    def getNumCompte(self):                # getter 
        return self.__numero_compte
    
    def setNumCompte(self, chNumcpt):      # setter 
        self.__numero_compte = chNumcpt
# getter
xy = CompteBancaire(1000,"ABCDEFGH")
print(xy.getNumCompte())
# setter
xy.setNumCompte("VWXYZHRST")
print(xy.getNumCompte())
  • Exemple : Attribut privé non accessible depuis la sous classe
class Vehicule:
    """
    Classe "Vehicule" représentant un modèle générique de véhicule
    """

    def __init__(self, couleur='noire', vitesse=0, roues=4):
        self.couleur = couleur
        self.vitesse = vitesse
        self.roues = roues
        self.__numero_serie = "V123XYZ"  # attribut privé

    def afficher_infos(self):
        print("Couleur :", self.couleur)
        print("Vitesse :", self.vitesse)
        print("Nombre de roues :", self.roues)
        print("Numéro de série (dans la classe mère) :", self.__numero_serie)


class Voiture(Vehicule):
    """
    Classe fille "Voiture" héritant de "Vehicule"
    """

    def __init__(self, couleur='rouge', vitesse=0):
        super().__init__(couleur, vitesse, roues=4)

    def afficher_infos_voiture(self):
        print("Couleur :", self.couleur)
        print("Vitesse :", self.vitesse)
        print("Nombre de roues :", self.roues)
        
        # Tentative d’accès à l’attribut privé
        try:
            print("Numéro de série (dans la classe fille) :", self.__numero_serie)
        except AttributeError as e:
            print("Erreur :", e)

# Test
v = Voiture("bleue", 120)
v.afficher_infos_voiture()
Type d'attribut Syntaxe Accessible de l'extérieur ? Accès dans sous-classe ? Name mangling ?
Public attribut Oui Oui Non
Protégé _attribut Oui ( déconseillé) Oui Non
Privé __attribut Non (sauf via _Classe__attribut) Non (sauf contournement) Oui

- Héritage multiple

( lien )

import datetime
#classe mère 1
class Personne:
  def __init__(self,n,p,d):
      self.nom=n
      self.prenom=p
      self.dateNaiss=d
  def AfficherInfos(self):
      print("nom: ",self.nom,"prénom: ",self.prenom,"date de naissance : ",self.dateNaiss)
#classe mère 2 
class Employe:
  def __init__(self,code,sal):
      self.code=code
      self.salaire=sal
  def AfficherInfos(self):
      print("code:",self.code," salaire: ",self.salaire)
class Prof(Employe,Personne):
  def __init__(self,n,p,d,cod,sal,specialite):
       Personne.__init__(self,n,p,d)
       Employe.__init__(self,cod,sal)
       self._sp=specialite
  def AfficherInfos(self):
      Personne.AfficherInfos(self)
      Employe.AfficherInfos(self)
      print("Specialité: ", self._sp)

unPr = Prof("Omar","Benahmed","21/11/2003",5267,8500,"Lit Fr")
print(unPr.AfficherInfos())
# super() 
# super()
class Proff(Personne,Employe):
  def __init__(self,n,p,d,cod,sal,specialite):
       super().__init__(n,p,d)
       super().__init__(self,cod,sal)
       self._sp=specialite
  def AfficherInfos(self):
      Personne.AfficherInfos(self)
      Employe.AfficherInfos(self)
      print("Specialité: ", self._sp)

unPr = Proff("Ali","Benahmed","21/11/2003",5267,6000,"Lit Fr")
print(unPr.AfficherInfos())
class Prof(Employe,Personne):
   def __init__(self,n,p,d,cod,sal,specialite):
       Employe.__init__(self,cod,sal)
       super().__init__(n,p,d)
       self._sp=specialite
   def AfficherInfos(self):
       super().AfficherInfos()
       Employe.AfficherInfos(self)
       print("Specialité: ", self._sp)
unPr = Prof("Ali","Benahmed","21/11/2003",5267,6000,"Lit Fr")
print(unPr.AfficherInfos())

super() : pour la 1ère classe dans l'ordre d'apparition

class Prof(Personne,Employe):
   def __init__(self,n,p,d,cod,sal,specialite):
       super().__init__(n,p,d)
       Employe.__init__(self,cod,sal)
       self._sp=specialite
   def AfficherInfos(self):
       super().AfficherInfos()
       Employe.AfficherInfos(self)
       print("Specialité: ", self._sp)
unPr = Prof("Ali","Benahmed","21/11/2003",5267,6000,"Lit Fr")
print(unPr.AfficherInfos())

    Type at least 2 letters. ↑ ↓ to move, Enter to open.