Python prend en charge trois types de méthodes dans les définitions de classes : les méthodes d'instance, les méthodes de classe et les méthodes statiques. Elles diffèrent par la manière dont elles sont appelées et par leur accès aux données de la classe et de l'instance.
Historique :
À l'origine, les méthodes d'instance (celles avec "self") étaient le seul type de comportement, on supposait que les méthodes appelaient toujours un comportement ou modifiaient/lisaient les données d'un objet spécifique. Plus tard, Python a introduit les méthodes de classe (avec "cls"), fournissant un comportement pour la classe dans son ensemble (par exemple, des constructeurs alternatifs), et des méthodes statiques, semblables à des fonctions normales, mais liées à la classe.
Problématique :
Parfois, une fonctionnalité générale est nécessaire pour toutes les instances (méthodes statiques). Parfois, une opération doit être accessible "pour toute la classe" (par exemple, la création d'une instance). Cela étant dit, si le type de méthode est mal défini — cela peut provoquer des bugs (par exemple, essayer accidentellement de modifier la classe via une méthode d'instance, ou vice versa).
Solution :
Exemple de code :
class MyClass: def instance_method(self): return f"Instance : {self}" @classmethod def class_method(cls): return f"Classe : {cls}" @staticmethod def static_method(): return "Ceci est une méthode statique" obj = MyClass() print(obj.instance_method()) # Instance : <MyClass object...> print(MyClass.class_method()) # Classe : <class 'MyClass'> print(MyClass.static_method())# Ceci est une méthode statique
Caractéristiques clés :
Peut-on appeler une méthode d'instance directement à partir de la classe ?
Oui, mais il est nécessaire de transmettre explicitement l'objet :
MyClass.instance_method(obj)
ce qui est rarement approprié.
Comportement des méthodes statiques lors de l'héritage : peuvent-elles être redéfinies ?
Oui, on peut déclarer une staticmethod dans une classe enfant avec le même nom, et c'est celle-ci qui sera appelée lorsque appelée à partir de l'héritier.
À quoi servent les méthodes de classe si l'on peut toujours utiliser des méthodes statiques avec cls comme argument ?
cls n'est pas simplement le premier argument : dans classmethod, Python substitue lui-même la classe correspondante comme cls, même si l'appel provient d'un héritier. Cela permet de créer une hiérarchie alternative de constructeurs sans lien strict avec le parent.
Exemple :
class Base: @classmethod def make(cls): return cls() class Child(Base): pass Child.make() # renverra Child, pas Base
Dans le projet, des méthodes normales étaient utilisées pour créer des instances alternatives (par exemple, create_from_json). En raison de cela, lors de l'héritage, la méthode retournait toujours un objet de la classe de base, et non celui de l'héritier.
Avantages :
Inconvénients :
Des usines classmethod ont été mises en œuvre, qui retournent des instances de la classe actuelle (cls()), même lorsqu'elles sont appelées depuis un héritier.
Avantages :
Inconvénients :