constructeur et destructeur en Python

25 Apr 2019 25 Apr 2019 26653 vues ESSADDOUKI Mostafa 6 min de lecture

Constructeur — __init__

Les constructeurs sont utilisés pour instancier un objet. Leur rôle est d'initialiser les attributs de la classe au moment de la création de l'objet. En Python, cette tâche est assurée par la méthode spéciale __init__(), appelée automatiquement dès qu'un objet est créé.


Syntaxe Python
def __init__(self, liste_parametres):
    self.attribut = valeur   # initialisation des attributs

Types de constructeurs

TypeDescriptionExemple d'appel
Constructeur par défautN'accepte aucun argument autre que self. Initialise les attributs avec des valeurs fixes.obj = MaClasse()
Constructeur paramétréAccepte des arguments fournis par le programmeur pour personnaliser l'initialisation.obj = MaClasse(val1, val2)
Remarque — Un seul constructeur en Python Contrairement à C++ ou Java, Python ne permet de définir qu'un seul constructeur par classe. Pour simuler plusieurs constructeurs, on utilise des valeurs par défaut ou des méthodes de classe (@classmethod).

Exemple — Constructeur par défaut

class Personne:
    def __init__(self):
        self.nom    = "Inconnu"
        self.prenom = "Inconnu"

    def afficher(self):
        print(f"Nom : {self.nom} | Prénom : {self.prenom}")

p = Personne()
p.afficher()
Sortie
Nom : Inconnu | Prénom : Inconnu

Exemple — Constructeur paramétré

class Personne:
    def __init__(self, nom, prenom, ville="Meknès"):
        self.nom    = nom
        self.prenom = prenom
        self.ville  = ville

    def afficher(self):
        print(f"Nom : {self.nom} | Prénom : {self.prenom} | Ville : {self.ville}")

p1 = Personne('ESSADDOUKI', 'Mostafa')
p2 = Personne('Kayouh', 'Mohamed', 'Rabat')

p1.afficher()
p2.afficher()
Sortie
Nom : ESSADDOUKI | Prénom : Mostafa  | Ville : Meknès
Nom : Kayouh     | Prénom : Mohamed  | Ville : Rabat

Exemple — Plusieurs constructeurs avec @classmethod

class Personne:
    def __init__(self, nom, prenom):
        self.nom    = nom
        self.prenom = prenom

    @classmethod
    def depuis_chaine(cls, chaine):
        """Constructeur alternatif depuis une chaîne 'NOM Prénom'."""
        nom, prenom = chaine.split()
        return cls(nom, prenom)

p1 = Personne('ESSADDOUKI', 'Mostafa')
p2 = Personne.depuis_chaine('KAYOUH Mohamed')

print(p1.nom, p1.prenom)   # ESSADDOUKI Mostafa
print(p2.nom, p2.prenom)   # KAYOUH Mohamed

Destructeur — __del__

Les destructeurs sont appelés lorsqu'un objet est détruit, c'est-à-dire lorsque toutes ses références sont supprimées et que le ramasse-miettes (garbage collector) libère la mémoire.

Définition — Destructeur La méthode __del__() est le destructeur Python. Elle est invoquée automatiquement quand le compteur de références de l'objet tombe à zéro. Elle permet d'effectuer des opérations de nettoyage : fermer un fichier, libérer une connexion, vider une structure, etc.

Syntaxe Python
def __del__(self):
    # opérations de nettoyage
    ...
Python vs C++ En C++, la gestion manuelle de la mémoire rend les destructeurs indispensables. En Python, le ramasse-miettes gère automatiquement la mémoire, rendant __del__ rarement nécessaire. Préférez le gestionnaire de contexte (with / __enter__ / __exit__) pour les ressources critiques.

Exemple 1 — Destruction explicite avec del

En utilisant le mot-clé del, on supprime toutes les références à l'objet, ce qui déclenche automatiquement l'appel au destructeur.

class Tableau:

    def __init__(self):
        self.donnee = [0] * 100    # tableau de 100 éléments
        print(f"Tableau créé ({len(self.donnee)} éléments)")

    def __del__(self):
        print("Destructeur appelé — tableau vidé")
        self.donnee.clear()

tab = Tableau()
del tab    # supprime la référence → déclenche __del__
Sortie
Tableau créé (100 éléments)
Destructeur appelé — tableau vidé

Exemple 2 — Le destructeur s'exécute après la fin du programme

Le destructeur est appelé lorsque le nombre de références tombe à zéro, pas nécessairement quand l'objet sort de la portée locale. Dans l'exemple ci-dessous, l'objet est retourné par la fonction et reste référencé dans p1 jusqu'à la fin du programme.

class Personne:

    def __init__(self, nom, prenom):
        self.nom    = nom
        self.prenom = prenom

    def __del__(self):
        print(f"Destructeur appelé pour {self.nom}")

def creation():
    print("Création de l'objet...")
    p = Personne('ESSADDOUKI', 'Mostafa')
    print("Fin de création")
    return p        # l'objet est retourné → toujours référencé

print("Début du programme")
p1 = creation()
print("Fin du programme")
# __del__ est appelé ICI, après la fin de main, quand p1 est libéré
Sortie
Début du programme
Création de l'objet...
Fin de création
Fin du programme
Destructeur appelé pour ESSADDOUKI
Point clé — Moment d'appel du destructeur Le destructeur est appelé lorsque le nombre de références à l'objet tombe à zéro, et non pas quand l'objet sort de la portée d'une fonction. Tant qu'une variable externe (p1) référence l'objet, il reste en vie.

Exemple 3 — Référence circulaire

Une référence circulaire se produit quand deux objets se référencent mutuellement. Le ramasse-miettes Python détecte généralement ce cas, mais un __del__ personnalisé peut perturber ce mécanisme.

class A:
    def __init__(self, b):
        self.b = b          # A référence B

class B:
    def __init__(self):
        self.a = A(self)    # B référence A → référence circulaire

    def __del__(self):
        print("Destructeur de B appelé")

def creation():
    b = B()                 # b sort de portée ici

creation()
print("Fin de creation()")
Sortie
Destructeur de B appelé
Fin de creation()
Danger — Références circulaires avec __del__ Lorsque des objets impliqués dans une référence circulaire définissent un __del__, le ramasse-miettes ne sait pas dans quel ordre les détruire et peut les laisser en mémoiredurant toute la durée d'exécution du programme. Pour les ressources critiques, utilisez plutôt le protocole de contexte :
class Ressource:
    def __enter__(self):
        print("Ouverture")
        return self

    def __exit__(self, *args):
        print("Fermeture — garanti même en cas d'erreur")

with Ressource() as r:
    pass   # __exit__ appelé automatiquement

Cycle de vie d'un objet Python

ÉtapeMéthode appeléeDéclencheur
Création__new__(cls)Allocation mémoire — avant __init__
Initialisation__init__(self, ...)Juste après la création de l'objet
UtilisationMéthodes de l'objetDurant la durée de vie
Destruction__del__(self)Compteur de références = 0
POO

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.