Attributs et instances de classe#

Rappels#

Voici un exemple de classe qui contient une méthode :

class MaClasse
    def ma_méthode(self):
        print(self.mon_attribut)

Le bloc indenté en-dessous du mot-clé class s’appelle le corps de la classe. Et les méthodes sont définies avec le mot-clé def dans le corps de la classe.

On dit que ce sont des méthodes d’instance parce qu’il faut créer une instance pour pouvoir les appeler :

mon_instance = MaClasse()
mon_instance.ma_méthode()

Attributs de classes#

On peut également déclarer des variables dans le corps d’une classe.

On crée ainsi des attributs de classe :

class MaClasse:
    mon_attribut_de_classe = 42

Ici mon_attribut_de_classe existe à la fois dans les instances de MaClasse et dans la classe elle-même :

print(MaClasse.mon_attribut_de_classe)
# affiche: 42
mon_instance = MaClasse()
print(mon_instance.mon_attribut_de_classe)
# affiche: 42

Un point important est que les attributs de classe sont partagés entre toutes les instances. Voici un exemple d’utilisation possible :

class Voiture:
    nombre_total_de_voitures_fabriquées = 0

    def __init__(self, marque, couleur):
        print("Construction d'une", marque, couleur)
        Voiture.nombre_total_de_voitures_fabriquées += 1


ferrari_1 = Voiture("Ferrari", "rouge")
mercedes_1  = Voiture("Mercedes, "noire")
ferrari_2 = Voiture("Ferrari", "rouge")
print("total:", Voiture.nombre_total_de_voitures_fabriquées)
# affiche:
# Construction d'une Ferrari rouge
# Construction d'une Mercedes noire
# Construction d'une Ferrari rouge
# total: 3

Notez que pour changer l’attribut de classe depuis une méthode, (comme dans la méthode __init__ ci-dessus) on utilise le nom de la classe directement, et non pas self.

Méthodes de classes#

On peut aussi définir des méthodes de classes avec le décorateur classmethod.

Dans ce cas, le premier argument s’appelle cls et prend la valeur de la classe elle-même. Pour poursuivre sur notre exemple :

class Voiture:
    nombre_total_de_voitures_fabriquées = 0

    def __init__(self, marque, couleur):
        print("Construction d'une", marque, couleur)
        Voiture.nombre_total_de_voitures_fabriquées += 1

    @classmethod
    def fabrique_ferrari(cls):
        return cls("ferrari", "rouge")


ferrari = Voiture.fabrique_ferrari()

Détaillons ce qu’il se passe sur la dernière ligne : à gauche du signe égal, il y a une variable, et à droite une expression (Voiture.fabrique_ferrari())

L’expression est constitué d’une classe à gauche du point (Voiture), et d’un attribut à droite du point fabrique_ferrari, suivi de parenthèses.

Comme fabrique_ferrari est une méthode de classe, on va appeler la méthode de classe fabrique_ferrari en lui passant la classe courante en argument.

On arrive ainsi dans le corps de la méthode de classe fabrique_ferrari, et cls vaut la classe Voiture.

Finalement, on évalue l’expression cls("ferrari", rouge") en remplaçant cls par sa valeur, ce qui donne Voiture("ferrari", "rouge") qui correspond bien à ce qu’on obtient : Une instance de la classe Voiture.