
Variables de classe vs. variables d'instance
Distinguez les variables de classe (partagées par toutes les instances) des variables d'instance (propres à chaque objet) en Python. Apprenez à les définir, à les utiliser, et à comprendre leurs implications.
Variables d'instance : propres à chaque objet
Les variables d'instance (ou attributs d'instance) sont les variables les plus courantes dans les classes Python. Elles sont spécifiques à chaque objet (chaque instance de la classe).
Chaque objet a sa propre copie des variables d'instance. Modifier une variable d'instance d'un objet n'affecte pas les autres objets de la même classe.
Les variables d'instance sont généralement définies dans le constructeur (`__init__`), en utilisant `self.nom_variable = valeur`.
Exemple :
class Voiture:
def __init__(self, marque, modele, couleur):
self.marque = marque # Variable d'instance
self.modele = modele # Variable d'instance
self.couleur = couleur # Variable d'instance
# Création de deux objets Voiture
voiture1 = Voiture("Renault", "Clio", "rouge")
voiture2 = Voiture("Peugeot", "208", "bleue")
# Chaque objet a ses propres valeurs pour les variables d'instance
print(voiture1.marque) # Affiche Renault
print(voiture2.marque) # Affiche Peugeot
voiture1.couleur = "verte"
print(voiture1.couleur) # Affiche verte
print(voiture2.couleur) # Affiche bleue (non affectée par la modification de voiture1)Dans cet exemple, `marque`, `modele`, et `couleur` sont des variables d'instance. Chaque objet `Voiture` a ses propres valeurs pour ces variables.
Variables de classe : partagées par toutes les instances
Les variables de classe (ou attributs de classe) sont des variables qui sont partagées par tous les objets de la classe. Il n'y a qu'une seule copie de chaque variable de classe, quel que soit le nombre d'objets créés.
Les variables de classe sont définies directement dans le corps de la classe (en dehors de toute méthode).
Elles sont souvent utilisées pour stocker des constantes ou des valeurs qui sont communes à tous les objets de la classe.
Exemple :
class Voiture:
roues = 4 # Variable de classe (toutes les voitures ont 4 roues, par défaut)
def __init__(self, marque, modele):
self.marque = marque
self.modele = modele
# Création d'objets
voiture1 = Voiture("Renault", "Clio")
voiture2 = Voiture("Peugeot", "208")
# Accès à la variable de classe
print(voiture1.roues) # Affiche 4 (accès via une instance)
print(voiture2.roues) # Affiche 4 (accès via une instance)
print(Voiture.roues) # Affiche 4 (accès via la classe)
# Modification de la variable de classe
Voiture.roues = 6 # Toutes les voitures ont maintenant 6 roues (même celles déjà créées !)
print(voiture1.roues) # Affiche 6
print(voiture2.roues) # Affiche 6Dans cet exemple, `roues` est une variable de classe. Elle est partagée par tous les objets `Voiture`.
Notez que si vous modifiez la variable de classe *via la classe* (`Voiture.roues = 6`), la modification est répercutée sur tous les objets. Cependant, si vous modifiez la variable de classe *via une instance* (`voiture1.roues = 6`), vous créez en fait une nouvelle variable d'instance `roues` pour cet objet spécifique, qui masque la variable de classe (c'est généralement une mauvaise pratique).
Accéder et modifier les variables de classe
Vous pouvez accéder à une variable de classe de deux manières :
- Via la classe elle-même : `NomDeLaClasse.variable_de_classe`
- Via une instance de la classe : `objet.variable_de_classe` (mais attention au masquage, voir ci-dessous)
Il est généralement recommandé d'accéder aux variables de classe via la classe elle-même (`NomDeLaClasse.variable_de_classe`), pour plus de clarté.
Pour modifier une variable de classe, il est *fortement* recommandé de le faire via la classe elle-même (`NomDeLaClasse.variable_de_classe = nouvelle_valeur`).
Si vous essayez de modifier une variable de classe via une instance (`objet.variable_de_classe = nouvelle_valeur`), vous ne modifierez pas la variable de classe. Au lieu de cela, vous créerez une *nouvelle variable d'instance* avec le même nom, qui masquera la variable de classe pour cet objet spécifique.
Exemple (illustrant le masquage) :
class MaClasse:
x = 10 # Variable de classe
obj1 = MaClasse()
obj2 = MaClasse()
print(obj1.x, obj2.x, MaClasse.x) # Affiche 10 10 10
obj1.x = 20 # Crée une variable d'INSTANCE x pour obj1 (masque la variable de classe)
print(obj1.x, obj2.x, MaClasse.x) # Affiche 20 10 10 (obj1.x est maintenant une variable d'instance)
MaClasse.x = 30 # Modifie la variable de CLASSE
print(obj1.x, obj2.x, MaClasse.x) # Affiche 20 30 30 (obj2.x et MaClasse.x ont été modifiés)Ce comportement peut être source d'erreurs si vous n'êtes pas attentif. Pour modifier une variable de classe, faites-le toujours via la classe elle-même.
Quand utiliser des variables de classe ou d'instance ?
Voici quelques indications pour choisir entre variables de classe et variables d'instance :
- Variables d'instance : Utilisez-les pour les données qui sont spécifiques à chaque objet (la plupart des cas). Par exemple, le nom, l'âge, la couleur d'un animal sont des variables d'instance.
- Variables de classe : Utilisez-les pour les données qui sont partagées par tous les objets de la classe, comme des constantes, des compteurs d'instances, ou des valeurs par défaut. Par exemple, le nombre de pattes d'un animal (en général) pourrait être une variable de classe (4 pour la plupart des animaux, 2 pour les humains, etc.).
Si vous n'êtes pas sûr, commencez par une variable d'instance. Vous pourrez toujours la transformer en variable de classe plus tard si nécessaire.
Variables de classe et méthodes de classe/statiques (notions avancées)
Les variables de classe sont souvent utilisées en conjonction avec les méthodes de classe (`@classmethod`) et les méthodes statiques (`@staticmethod`).
- Méthodes de classe : Elles prennent la classe elle-même comme premier argument (généralement nommé `cls`), au lieu de l'instance (`self`). Elles peuvent accéder et modifier les variables de classe.
- Méthodes statiques : Elles ne prennent ni la classe ni l'instance comme premier argument. Elles sont liées à la classe, mais ne peuvent pas accéder directement aux variables de classe ou d'instance (sauf si elles les reçoivent en argument). Elles servent généralement de fonctions utilitaires liées à la classe.
Ces concepts seront abordés plus en détail dans les sections sur les méthodes de classe et statiques.