Vous souhaitez vous initier à la conception orientée objet en Python ? Faites les premiers pas dès aujourd’hui en découvrant la méthode __init__ de Python.
Dans ce tutoriel, nous aborderons les bases des classes et des objets Python, puis nous nous pencherons sur la méthode __init__
.
À la fin de ce tutoriel, vous serez en mesure de répondre aux questions suivantes :
- Qu’est-ce qu’une variable d’instance ou un attribut d’instance ?
- Comment la méthode init aide-t-elle à initialiser les attributs d’instance ?
- Comment pouvons-nous définir des valeurs par défaut pour les attributs ?
- Comment pouvons-nous utiliser les méthodes de classe comme constructeurs pour créer des objets ?
Commençons.
Classes et objets Python
Les classes sont fondamentales pour la programmation orientée objet en Python. Nous pouvons créer une classe et définir des attributs et des méthodes pour lierdes données et des fonctionnalités associées.
Une fois que nous avons créé une classe, nous pouvons l’utiliser comme plan (ou modèle) pour créer des objets (instances).
👩🏫Example – C’est l’heure de la création ! Créons une classe Employé
dont chaque objet possède les attributs suivants :
full_name
: le nom complet de l’employé au formatfirstName lastName
emp_id
: l’identifiant de l’employédepartment
: le département auquel l’employé appartientexperience
: le nombre d’années d’expérience de l’employé
Qu’est-ce que cela signifie ? 🤔
Chaque employé est une instance ou un objet de la classe Employee
. Et chaque objet aura sa propre valeur pour les attributs full_name
, emp_id
, department
et experience
.
Ces attributs sont également appelés variables d’instance, et nous utiliserons indifféremment les termes attributs et variables d’instance.
Nous reviendrons plus tard sur l’ajout d’attributs. Pour l’instant, nous créons une classe Employé
comme suit :
classe Employé :
pass
L’utilisation de pass
(en tant qu’espace réservé) nous permet d’éviter les erreurs lors de l’exécution du script.
Bien que la version actuelle de la classe Employee
ne soit pas très utile, il s’agit toujours d’une classe valide. Nous pouvons donc créer des objets de la classe Employee
:
employee_1 = Employee()
print(employee_1)
#Output : <__main__.Employee object at 0x00FEE7F0>
Nous pouvons également ajouter des attributs et les initialiser avec des valeurs comme indiqué :
employee_1.full_name = 'Amy Bell'
employee_1.department = 'HR'
Mais cette approche de l’ajout d’attributs d’instance est à la fois inefficace et sujette aux erreurs. De plus, elle ne permet pas d’utiliser la classe comme modèle pour créer des objets. C’est là que la méthode __init__
est utile.
Comprendre le rôle de la méthode __init__ dans une classe Python
Nous devrions être en mesure d’initialiser les variables d’instance lors de l’instanciation d’un objet et la méthode __init__
nous aide à le faire. La méthode __init__
est appelée à chaque fois qu’un nouvel objet de la classe est créé pour initialiser les valeurs des variables d’instance.
Si vous avez programmé dans un langage comme le C, vous verrez que la méthode __init__
fonctionne de la même manière que les constructeurs.
Définition de la méthode __init__
Ajoutons la méthode __init__
à la classe Employé
:
classe Employé :
def __init__(self, full_name,emp_id,department,experience) :
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = expérience
Le paramètre self
fait référence à l’instance de la classe et le paramètre self.attribute
initialise l’attribut de
l’instance à la valeur indiquée à droite.
Nous pouvons maintenant créer des objets comme suit :
employee_2 = Employee('Bella Joy','M007','Marketing',3)
print(employee_2)
# Output : <__main__.Employee object at 0x017F88B0>
Lorsque nous imprimons les objets employés, nous n’obtenons aucune information utile, à l’exception de la classe à laquelle ils appartiennent. Ajoutons une méthode __repr__
qui définit une chaîne de représentation pour la classe :
def __repr__(self) :
return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."
En ajoutant le __repr__
à la classe Employee
, nous obtenons :
classe Employé :
def __init__(self, full_name,emp_id,department,experience) :
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = expérience
def __repr__(self) :
return f"{self.full_name},{self.emp_id} from {self.department} with {self.experience} years of experience."
Les objets employés disposent désormais d’une chaîne de représentation utile :
print(employee_2)
# Output : Bella Joy,M007 de Marketing avec 3 ans d'expérience.
Quelques conventions
Avant de poursuivre, voici quelques remarques :
- Nous avons utilisé
self
comme premier paramètre de la méthode__init__
pour faire référence à l’instance de la classe elle-même et nous avons utiliséself.attribute_name
pour initialiser les différents attributs. L’utilisation deself
est la convention préférée (vous pouvez cependant utiliser n’importe quel autre nom). - Lors de la définition de la méthode
__init__
, nous avons défini les noms des paramètres dans les définitions__init__
de manière à ce qu’ils correspondent aux noms des attributs. Cela améliore la lisibilité.
Comment ajouter des valeurs par défaut aux attributs ?
Dans l’exemple que nous avons codé jusqu’à présent, tous les attributs sont obligatoires. La création d’un objet n’est réussie que si nous transmettons les valeurs de tous les champs au constructeur.
Essayez d’instancier un objet de la classe Employee sans passer la valeur de l’attribut experience :
employee_3 = Employee('Jake Lee','E001','Engineering')
Vous obtiendrez l’erreur suivante :
Traceback (dernier appel le plus récent) :
File "main.py", line 22, in <module>
employee_3 = Employee('Jake Lee', 'E001', 'Engineering')
TypeError : __init__() missing 1 required positional argument : 'experience'
Mais si vous souhaitez rendre certains attributs optionnels, vous pouvez le faire en fournissant des valeurs par défaut pour ces attributs lors de la définition de la méthode __init__
.
Ici, nous fournissons une valeur par défaut de 0
pour l’attribut ” experience
” :
classe Employé :
def __init__(self, full_name,emp_id,department,experience=0) :
self.full_name = full_name
self.emp_id = emp_id
self.department = department
self.experience = expérience
def __repr__(self) :
return f"{self.full_name},{self.emp_id} de {self.department} avec {self.experience} années d'expérience."
L’objet employee_3
est créé sans valeur pour l’attribut experience
; la valeur par défaut de 0 est utilisée pour l’expérience
.
employee_3 = Employee('Jake Lee','E001','Engineering')
print(employee_3.experience)
# Sortie : 0
Constructeurs de classe alternatifs utilisant les méthodes de classe
Jusqu’à présent, nous avons seulement vu comment définir la méthode __init__
et définir des valeurs par défaut pour les attributs lorsque cela est nécessaire. Nous savons également que nous devons passer les valeurs des attributs requis dans le constructeur.
Parfois, cependant, les valeurs de ces variables d’instance (ou attributs) peuvent être disponibles dans une structure de données différente, telle qu’un tuple, un dictionnaire ou une chaîne JSON.
Que faire alors ?
Prenons un exemple. Supposons que les valeurs de la variable d’instance se trouvent dans un dictionnaire Python :
dict_fanny = {'name' : 'Fanny Walker', 'id' : 'H203', 'dept' : 'HR', 'exp':2}
Nous pouvons puiser dans le dictionnaire et obtenir tous les attributs de la manière suivante :
name = dict_fanny['name']
id = dict_fanny['id']
dept = dict_fanny['dept']
exp = dict_fanny['exp']
Vous pouvez ensuite créer un objet en transmettant ces valeurs au constructeur de la classe :
employee_4 = Employee(name, id, dept, exp)
print(employee_4)
# Sortie : Fanny Walker,H203 de HR avec 2 ans d'expérience.
Rappelez-vous : vous devez procéder ainsi pour chaque nouvel objet que vous créez. Cette approche est inefficace et nous pouvons certainement faire mieux. Mais comment ?
En Python, nous pouvons utiliser les méthodes de classe comme constructeurs pour créer des objets de la classe. Pour créer une méthode de classe, nous utilisons le décorateur @classmethod.
Définissons une méthode qui analyse le dictionnaire, récupère les valeurs des variables d’instance et les utilise pour construire les objets Employee
.
@classmethod
def from_dict(cls,data_dict) :
full_name = data_dict['name']
emp_id = data_dict['id']
département = data_dict['dept']
expérience = data_dict['exp']
return cls(full_name, emp_id, department, experience)
Lorsque nous devons créer des objets en utilisant les données du dictionnaire, nous pouvons utiliser la méthode de classe from_dict()
.
remarquez l’utilisation de
cls
dans la méthode de classe au lieu deself
. De la même manière que nous utilisons self pour faire référence à l’instance,cls
est utilisé pour faire référence à la classe. De plus, les méthodes de classe sont liées à la classe et non aux objets.
Ainsi, lorsque nous appelons la méthode de classe from_dict()
pour créer des objets, nous l’appelons sur la classe Employee
:
emp_dict = {'name' : 'Tia Bell', 'id' : 'S270', 'dept' : 'Sales', 'exp':3}
employee_5 = Employee.from_dict(emp_dict)
print(employee_5)
# Sortie : Tia Bell,S270 de Ventes avec 3 ans d'expérience.
Maintenant que nous disposons d’un dictionnaire pour chacun des n
employés, nous pouvons utiliser la méthode de classe from_dict()
comme constructeur pour instancier des objets – sans avoir à récupérer les valeurs des variables instantanées dans le dictionnaire.
📝ANote sur les variables de classe
Nous avons défini ici la méthode de classe qui est liée à la classe et non aux instances individuelles. Tout comme les méthodes de classe, nous pouvons également avoir des variables de classe.
Comme les méthodes de classe, les variables de classe sont liées à la classe et non à une instance. Lorsqu’un attribut prend une valeur fixe pour toutes les instances de la classe, nous pouvons envisager de les définir comme des variables de classe.
FAQ
La méthode __init__
dans une définition de classe nous permet d’initialiser les attributs ou les variables d’instance de toutes les instances de la classe. La méthode __init__
est appelée chaque fois qu’une nouvelle instance de la classe est créée.
L’objectif d’avoir plusieurs méthodes __init__
dans une classe Python est de fournir plusieurs constructeurs qui instancient les objets. Mais vous ne pouvez pas définir plusieurs méthodes __init__
. Si vous définissez plusieurs méthodes __init__
, la deuxième et la plus récente implémentation écrasera la première. Cependant, vous pouvez utiliser le décorateur @classmethod
pour définir des méthodes de classe qui peuvent être utilisées comme constructeurs pour instancier des objets.
Si vous ne définissez pas la méthode __init__
, vous pouvez toujours instancier des objets. Toutefois, vous devrez ajouter manuellement des variables d’instance et attribuer des valeurs à chacune d’entre elles. Vous ne pourrez pas transmettre les valeurs des variables d’instance dans le constructeur. Cela n’est pas seulement source d’erreurs, mais va également à l’encontre de l’objectif d’avoir une classe comme modèle à partir duquel nous pouvons instancier des objets.
Oui, il est possible de fournir des valeurs par défaut pour un ou plusieurs attributs lors de la définition de la méthode __init__
. Fournir des valeurs par défaut permet de rendre ces attributs optionnels dans le constructeur. Les attributs prennent les valeurs par défaut lorsque nous ne transmettons pas les valeurs de ces attributs dans le constructeur.
Oui, vous pouvez toujours mettre à jour la valeur d’un attribut en dehors de la méthode __init__
. Vous pouvez également ajouter de nouveaux attributs de manière dynamique à une instance après l’avoir créée.
Conclusion
Dans ce tutoriel, nous avons appris à utiliser la méthode __init__
pour initialiser les valeurs des variables d’instance. Bien que cette méthode soit simple, elle peut être répétitive, en particulier lorsque vous avez beaucoup d’attributs.
Si vous êtes intéressé, vous pouvez explorer le module dataclasses. Dans Python 3.7 et les versions ultérieures, vous pouvez utiliser le module intégré des classes de données pour créer des classes de données qui stockent des données. Outre les implémentations par défaut de __init__
et d’autres méthodes couramment utilisées, elles sont dotées de nombreuses fonctionnalités intéressantes pour les indications de type, les valeurs par défaut complexes et l’optimisation.
Ensuite, apprenez-en plus sur if __name__==’__main__’ en Python.