@staticmethod vs @classmethod
@staticmethod agit comme une fonction ordinaire sans argument automatique ; @classmethod reçoit la classe comme cls et sert souvent de constructeur alternatif.
Comparaison point par point
#Premier argument
- @staticmethod
- Aucun
- @classmethod
cls(la classe)
Accès aux attributs de la classe
- @staticmethod
- Non, sauf via le nom de la classe écrit en dur
- @classmethod
- Oui, via
cls
Création d’un objet via cls(...)
- @staticmethod
- Non
- @classmethod
- Oui, c’est un usage typique
Comportement dans une classe dérivée
- @staticmethod
- Non applicable, aucune référence à la classe
- @classmethod
clsest la classe dérivée, pas la classe de base
Appel
- @staticmethod
Class.method(args)- @classmethod
Class.method(args)
Usage typique
- @staticmethod
- Validation, calculs indépendants des données de l’objet
- @classmethod
- Constructeurs alternatifs (from_text, from_dict)
Exemple
#class Grade:
def __init__(self, points):
self.points = points
@staticmethod
def is_valid(points):
return 0 <= points <= 100
@classmethod
def from_percent(cls, percent, maximum):
return cls(round(percent / 100 * maximum))
print(Grade.is_valid(120))
grade = Grade.from_percent(75, 80)
print(grade.points)Définition et utilisation
#Les deux décorateurs définissent une méthode que vous appelez par le nom de la classe, sans créer d’objet. Aucune des deux ne reçoit self, donc elle n’a pas accès aux données d’un objet précis.
Elles diffèrent par leur premier argument. Une méthode statique ne reçoit rien automatiquement : c’est une fonction ordinaire, simplement placée dans la classe pour l’organisation. Une méthode de classe reçoit comme premier argument la classe elle-même (cls), ce qui lui permet de référencer ses attributs et, surtout, de créer un objet via cls(...). Dans une classe dérivée, cls désigne cette classe dérivée, et non la classe où la méthode a été écrite.
Utilisez @staticmethod pour une fonction utilitaire qui appartient logiquement à la classe, par ex. une validation ou un calcul, mais qui n’a besoin ni de l’objet ni de la classe. Utilisez @classmethod quand la méthode doit créer des objets à partir de données dans un format différent du constructeur normal, par ex. from_text() ou from_dict(), ou quand elle a besoin d’accéder aux attributs de la classe, comme un compteur partagé.
Syntaxe
#class Name:
@staticmethod
def method(arg):
...
@classmethod
def other(cls, arg):
return cls(arg)Plus d’exemples
#class Task:
def __init__(self, number):
self.number = number
@classmethod
def from_code(cls, code):
return cls(code.removeprefix("tache_"))
class Quiz(Task):
pass
task = Quiz.from_code("tache_7_3")
print(type(task).__name__, task.number)class Course:
count = 0
def __init__(self, title):
self.title = title
Course.count += 1
@staticmethod
def slugify(title):
return title.lower().replace(" ", "-")
python_course = Course("Python pour débutants")
print(Course.slugify(python_course.title))
print(Course.count)Bonnes pratiques
#- Si une méthode n’utilise ni
selfnicls, elle devrait probablement être statique, ou même en dehors de la classe. - Nommez les constructeurs alternatifs avec le préfixe
from_, par ex.from_json(),from_row(). C’est une convention connue de la bibliothèque standard. - Dans une méthode de classe, créez les objets via
cls(...), et non avec le nom de la classe écrit en dur, pour qu’elle fonctionne correctement aussi dans les classes dérivées.
Vous voyez une erreur ou il manque un exemple ? Écrivez-nous.