En Python, je peux créer une méthode de classe en utilisant le décorateur @classmethod
:
>>> class C:
... @classmethod
... def f(cls):
... print(f'f called with cls={cls}')
...
>>> C.f()
f called with cls=<class '__main__.C'>
Alternativement, je peux utiliser une méthode normale (instance) sur une métaclasse:
>>> class M(type):
... def f(cls):
... print(f'f called with cls={cls}')
...
>>> class C(metaclass=M):
... pass
...
>>> C.f()
f called with cls=<class '__main__.C'>
Comme le montre la sortie de C.f()
, ces deux approches fournissent des fonctionnalités similaires.
Quelles sont les différences entre l'utilisation de @classmethod
Et l'utilisation d'une méthode normale sur une métaclasse?
Dans votre exemple, la différence serait dans certaines autres classes qui auront M défini comme leur métaclasse.
class M(type):
def f(cls):
pass
class C(metaclass=M):
pass
class C2(metaclass=M):
pass
C.f()
C2.f()
class M(type):
pass
class C(metaclass=M):
@classmethod
def f(cls):
pass
class C2(metaclass=M):
pass
C.f()
# C2 does not have 'f'
Voici plus sur les métaclasses Quels sont les cas d'utilisation (concrets) pour les métaclasses?
@Classmethod et Metaclass sont différents.
Tout dans python est un objet. Chaque chose signifie chaque chose.
Comme dit, chaque chose est un objet. Les classes sont également des objets, en fait, les classes sont des instances d'autres objets mystérieux formellement appelés méta-classes. La métaclasse par défaut dans python est "type" si non spécifié
Par défaut, toutes les classes définies sont des instances de type.
Les classes sont des instances de méta-classes
Peu de points importants sont de comprendre le comportement mentionné
Envisagez de suivre le code
class Meta(type):
def foo(self):
print(f'foo is called self={self}')
print('{} is instance of {}: {}'.format(self, Meta, isinstance(self, Meta)))
class C(metaclass=Meta):
pass
C.foo()
Où,
On peut vérifier que si "classe C" est une instance de "Class Meta
isinstance(C, Meta)
Les méthodes Python seraient liées. Comme python impose la restriction, cette méthode doit être invoquée uniquement avec l'instance. Parfois, nous pouvons souhaiter invoquer des méthodes directement via la classe sans aucune instance (un peu comme les membres statiques en Java) sans avoir à créer d'instance. Par exemple, une instance par défaut est requise pour appeler la méthode. Comme solution de contournement, python fournit une méthode de classe de fonction intégrée pour lier une méthode donnée à une classe au lieu d'une instance.
Comme les méthodes de classe sont liées à la classe. Il prend au moins un argument qui fait référence à la classe elle-même au lieu de l'instance (self)
si la méthode de classe fonction/décorateur intégrée est utilisée. Le premier argument sera la référence à la classe au lieu de l'instance
class ClassMethodDemo:
@classmethod
def foo(cls):
print(f'cls is ClassMethodDemo: {cls is ClassMethodDemo}')
Comme nous avons utilisé "classmethod", nous appelons la méthode "foo" sans créer d'instance comme suit
ClassMethodDemo.foo()
L'appel de méthode ci-dessus renverra True. Puisque le premier argument cls fait en effet référence à "ClassMethodDemo"
Résumé: