Aller au contenu

Programmation orientée objet#

courant

Classe de base#

class CompteBancaire:
    taux_interet = 0.02   # attribut de classe (partagé)

    def __init__(self, titulaire, solde=0):
        self.titulaire = titulaire   # attribut d'instance
        self.solde = solde

    def deposer(self, montant):
        self.solde += montant

    def __repr__(self):
        return f"CompteBancaire(titulaire={self.titulaire!r}, solde={self.solde})"

    def __str__(self):
        return f"Compte de {self.titulaire} ({self.solde}€)"

c = CompteBancaire("Ana", 100)
c.deposer(50)
print(c)   # Compte de Ana (150€)
print(repr(c)) # CompteBancaire(titulaire='Ana', solde=150)

Héritage#

class CompteEpargne(CompteBancaire):
    def __init__(self, titulaire, solde=0, taux=0.03):
        super().__init__(titulaire, solde)
        self.taux = taux

    def appliquer_interets(self):
        self.solde *= (1 + self.taux)

Méthodes spéciales (dunder) courantes#

Méthode Rôle
__init__ Constructeur
__str__ str(obj), print(obj)
__repr__ repr(obj), affichage interactif
__eq__ ==
__lt__ < (tri)
__len__ len(obj)
__iter__ / __next__ itération (for x in obj)
__getitem__ obj[i]
__enter__ / __exit__ context manager (with)
__call__ obj()

Encapsulation & propriétés#

Par convention, un attribut précédé d'un simple souligné _ est considéré comme interne/protégé.

Le décorateur @property permet de définir des attributs calculés en lecture seule, ou de valider les modifications via un setter.

class Rectangle:
    def __init__(self, largeur, hauteur):
        self.largeur = largeur
        self.hauteur = hauteur

    @property
    def aire(self):
        """Attribut calculé (lecture seule)."""
        return self.largeur * self.hauteur

    @property
    def largeur(self):
        return self._largeur

    @largeur.setter
    def largeur(self, valeur):
        if valeur <= 0:
            raise ValueError("la largeur doit être strictement positive")
        self._largeur = valeur
Pour aller plus loin : classes abstraites, héritage multiple (MRO) et name mangling
from abc import ABC, abstractmethod

class Forme(ABC):
    @abstractmethod
    def aire(self):
        ...

class Cercle(Forme):
    def __init__(self, rayon):
        self.rayon = rayon

    def aire(self):
        return 3.14159 * self.rayon ** 2
class A: ...
class B: ...
class C(A, B): ...

C.__mro__   # ordre de résolution des méthodes (Method Resolution Order)

Un double souligné __nom préfixe le nom avec _NomClasse pour éviter les collisions en cas d'héritage multiple. À réserver aux bibliothèques ; préférer la convention _nom au quotidien.

Méthodes de classe / statiques#