
Le constructeur __init__
Apprenez à utiliser le constructeur __init__ en Python pour initialiser les attributs de vos objets lors de leur création. Découvrez le rôle de 'self', les arguments du constructeur, et les bonnes pratiques.
Rôle du constructeur : initialiser un objet
Le constructeur est une méthode spéciale nommée `__init__` (avec deux tirets de soulignement avant et après) qui est automatiquement appelée lorsque vous créez un nouvel objet à partir d'une classe (instanciation).
Le rôle principal du constructeur est d'initialiser les attributs de l'objet, c'est-à-dire de leur donner une valeur initiale. C'est dans le constructeur que vous définissez l'état initial de l'objet.
Le constructeur peut également effectuer d'autres opérations d'initialisation, comme ouvrir un fichier, établir une connexion à une base de données, etc., mais son rôle principal est de définir les attributs.
Le constructeur est *implicitement* appelé, jamais *explicitement*.
Syntaxe : def __init__(self, ...):
La syntaxe du constructeur est la suivante :
class MaClasse:
def __init__(self, parametre1, parametre2, ...):
"""Docstring du constructeur (facultative, mais recommandée)."""
# Initialisation des attributs
self.attribut1 = parametre1
self.attribut2 = parametre2
# ... Autres opérations d'initialisation (facultatives) ...- `def __init__(...)`: Déclaration de la méthode spéciale `__init__`.
- `self` : Le premier paramètre est toujours `self`, qui fait référence à l'objet en cours de création.
- `parametre1, parametre2, ...` : Les autres paramètres (optionnels) sont les arguments que vous pouvez passer lors de la création de l'objet. Ils servent généralement à initialiser les attributs.
- `self.attribut1 = parametre1` : Initialisation des attributs de l'objet. On utilise `self.nom_attribut` pour créer et affecter une valeur à un attribut de l'objet.
Le paramètre self : l'objet lui-même
Le paramètre `self` est une référence à l'objet lui-même. Lorsque vous créez un objet à partir d'une classe, Python crée automatiquement cet objet en mémoire et le passe comme premier argument à la méthode `__init__` (et à toutes les autres méthodes d'instance).
A l'intérieur du constructeur (et des autres méthodes), vous utilisez `self` pour accéder aux attributs et aux méthodes de l'objet.
Exemple :
class Personne:
def __init__(self, nom, age):
self.nom = nom # Crée un attribut 'nom' pour l'objet et l'initialise avec la valeur de 'nom'
self.age = age # Crée un attribut 'age' pour l'objet et l'initialise avec la valeur de 'age'
def afficher_infos(self):
print(f"Nom : {self.nom}, Age : {self.age}")
# Création d'objets
p1 = Personne("Alice", 30)
p2 = Personne("Bob", 25)
# p1 et p2 sont deux objets différents, chacun avec ses propres attributs nom et age.
# self, dans __init__, fait référence à p1 lors de la création de p1, et à p2 lors de la création de p2.
p1.afficher_infos() # Affiche "Nom : Alice, Age : 30"
p2.afficher_infos() # Affiche "Nom : Bob, Age : 25"Sans `self`, vous ne pourriez pas distinguer les attributs des différents objets de la même classe.
Arguments du constructeur : personnaliser l'initialisation
Le constructeur peut prendre des arguments (en plus de `self`), qui permettent de personnaliser l'initialisation de l'objet.
Ces arguments sont passés lors de la création de l'objet, entre les parenthèses après le nom de la classe.
Exemple (avec la classe `Personne`) :
# Création d'objets avec des arguments
p1 = Personne("Alice", 30) # "Alice" est passé comme 'nom', 30 comme 'age'
p2 = Personne("Bob", 25) # "Bob" est passé comme 'nom', 25 comme 'age'Vous pouvez définir des valeurs par défaut pour les arguments du constructeur, comme pour les fonctions ordinaires :
class Personne:
def __init__(self, nom="Inconnu", age=0):
self.nom = nom
self.age = age
p3 = Personne() # Utilise les valeurs par défaut : nom="Inconnu", age=0
p4 = Personne("Charlie") # Utilise la valeur par défaut pour age : nom="Charlie", age=0
p5 = Personne(age=40) # Utilise la valeur par défaut pour nom, et un argument nommé pour age.Les arguments nommés et les valeurs par défaut s'appliquent également au constructeur.
__init__ n'est pas strictement un constructeur
Il est techniquement plus juste de considérer `__init__` comme un *initialiseur* plutôt que comme un *constructeur*.
En réalité, lorsque vous faites `MaClasse()`, Python appelle d'abord une autre méthode spéciale, `__new__`, pour créer l'objet en mémoire. Ensuite, il appelle `__init__` pour initialiser cet objet.
La méthode `__new__` est rarement redéfinie, sauf dans des cas avancés (métaclasses, singletons, etc.). Dans la grande majorité des cas, vous utiliserez `__init__` pour initialiser vos objets.
Il est courant de dire "constructeur" par abus de langage, mais il est bon de connaître la distinction.
Bonnes pratiques
Voici quelques bonnes pratiques pour l'utilisation du constructeur `__init__` :
- Initialisez tous les attributs d'instance dans `__init__` : Cela rend le code plus clair et évite les erreurs. Si un attribut n'est pas initialisé, il n'existe pas tant qu'il n'est pas affecté.
- Utilisez des docstrings : Documentez le constructeur, en expliquant le rôle des arguments.
- Validez les arguments : Si nécessaire, ajoutez du code dans le constructeur pour valider les arguments et lever des exceptions si les valeurs sont invalides (par exemple, vérifier qu'un rayon est positif).
- Utilisez des noms d'attributs clairs : Choisissez des noms d'attributs qui décrivent clairement leur contenu.
- Evitez la logique complexe dans `__init__` : Le constructeur doit principalement servir à initialiser les attributs. Si vous avez besoin d'effectuer des opérations complexes, il est préférable de les déplacer dans une méthode séparée.