web-dev-qa-db-fra.com

Que sont les "méthodes de classe" et les "méthodes d'instance" en Python?

Il y a eu une discussion dans le chat concernant une question (la question elle-même étant sans rapport avec celle-ci), qui a révélé que je ne sais peut-être pas Python que ce soit).

Dans mon esprit, bien que la terminologie diffère selon les langues, nous pouvons généralement classer les fonctions comme:

  • fonctions [gratuites]
  • méthodes statiques/fonctions membres statiques
  • méthodes non statiques/fonctions membres non statiques

Apparemment, dans Python il y a un autre type de fonction qui ne rentre pas dans les catégories ci-dessus, une qui est une méthode mais "ne connaît pas sa classe".

Que sont les "méthodes de classe" et les "méthodes d'instance" en Python?

38

La réponse courte

  • une méthode d'instance connaît son instance (et de là, sa classe)
  • une méthode de classe connaît sa classe
  • une méthode statique ne connaît pas sa classe ou son instance

La réponse longue

Méthodes de classe

Une méthode de classe appartient à la classe dans son ensemble. Il ne nécessite pas d'instance. Au lieu de cela, la classe sera automatiquement envoyée comme premier argument. Une méthode de classe est déclarée avec le @classmethod décorateur.

Par exemple:

class Foo(object):
    @classmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)
Foo.hello()
-> "Hello from Foo"
Foo().hello()
-> "Hello from Foo"

Méthodes d'instance

D'un autre côté, une méthode d'instance requiert une instance pour l'appeler et ne nécessite aucun décorateur. C'est de loin le type de méthode le plus courant.

class Foo(object):
    def hello(self):
        print("hello from %s" % self.__class__.__name__)
Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'self'

(note: ce qui précède est avec python3; avec python2 vous obtiendrez une erreur légèrement différente)

Méthodes statiques

Une méthode statique est similaire à une méthode de classe, mais n'obtiendra pas l'objet classe comme paramètre automatique. Il est créé en utilisant le @staticmethod décorateur.

class Foo(object):
    @staticmethod
    def hello(cls):
        print("hello from %s" % cls.__name__)

Foo.hello()
-> TypeError: hello() missing 1 required positional argument: 'cls'

Liens de documentation

Voici des liens vers la documentation appropriée de python3:

Le documentation du modèle de données a ceci à dire sur la différence entre les méthodes de classe et les méthodes statiques:

Objets de méthode statiques Les objets de méthode statiques permettent de vaincre la transformation des objets fonction en objets de méthode décrits ci-dessus. Un objet de méthode statique est un wrapper autour de tout autre objet, généralement un objet de méthode défini par l'utilisateur. Lorsqu'un objet de méthode statique est extrait d'une classe ou d'une instance de classe, l'objet réellement renvoyé est l'objet encapsulé, qui n'est soumis à aucune autre transformation. Les objets de méthode statique ne sont pas eux-mêmes appelables, bien que les objets qu'ils enveloppent le soient généralement. Les objets de méthode statique sont créés par le constructeur staticmethod () intégré.

Objets de méthode de classe Un objet de méthode de classe, comme un objet de méthode statique, est un wrapper autour d'un autre objet qui modifie la façon dont cet objet est extrait des classes et les instances de classe. Le comportement des objets de méthode de classe lors d'une telle récupération est décrit ci-dessus, sous "Méthodes définies par l'utilisateur". Les objets de méthode de classe sont créés par le constructeur classmethod () intégré.

Questions connexes

50
Bryan Oakley

Que sont les "méthodes de classe" et les "méthodes d'instance" en Python?

  • Une "méthode d'instance" utilise les informations contenues dans l'instance pour déterminer la valeur à renvoyer (ou l'effet secondaire à effectuer). Ce sont très courants.

  • Une "méthode de classe" utilise des informations sur la classe (et non une instance de cette classe) pour affecter ce qu'elle fait (elles sont généralement utilisées pour créer de nouvelles instances en tant que constructeurs alternatifs, et ne sont donc pas incroyablement courantes).

  • Une "méthode statique" n'utilise aucune information sur la classe ou l'instance pour calculer ce qu'elle fait. C'est généralement juste dans la classe pour plus de commodité. (En tant que tels, ceux-ci ne sont pas très courants non plus.)

Une fonction de X

Rappelez-vous la classe de mathématiques, "y est une fonction de x, f(x)?" Appliquons cela dans le code:

y = function(x)

Cela implique que, puisque x peut changer, y peut changer lorsque x change. C'est ce que l'on entend lorsque nous disons que "y est une fonction de x"

Que sera y lorsque z sera 1? 2? 'FooBarBaz'?

y n'est pas une fonction de z, donc z peut être n'importe quoi et ne pas affecter le résultat de la fonction en supposant que notre function est une fonction pure. (S'il accède à z en tant que variable globale, ce n'est pas une fonction pure - c'est ce que l'on entend par pureté fonctionnelle.)

Gardez cela à l'esprit lorsque vous lisez les descriptions suivantes:

Méthodes d'instance

Une méthode d'instance est une fonction qui est une fonction de une instance . La fonction accepte implicitement l'instance comme argument et l'instance est utilisée par la fonction pour déterminer la sortie de la fonction.

Un exemple intégré d'une méthode d'instance est str.lower:

>>> 'ABC'.lower()
'abc'

str.lower est appelé sur l'instance de la chaîne et utilise les informations contenues dans l'instance pour déterminer la nouvelle chaîne à renvoyer.

Méthodes de classe:

N'oubliez pas qu'en Python, tout est un objet. Cela signifie que la classe est un objet et peut être passée comme argument à une fonction.

Une méthode de classe est une fonction qui est une fonction de la classe . Il accepte la classe comme argument.

Un exemple intégré est dict.fromkeys:

>>> dict.fromkeys('ABC')
{'C': None, 'B': None, 'A': None}

La fonction connaît implicitement sa propre classe, la fonction utilise la classe pour affecter la sortie de la fonction, et elle en crée une nouvelle à partir de l'itérable. Un OrderedDict le démontre lors de l'utilisation de la même méthode:

>>> from collections import OrderedDict
>>> OrderedDict.fromkeys('ABC')
OrderedDict([('A', None), ('B', None), ('C', None)])

La méthode de classe utilise des informations sur la classe (et non une instance de cette classe) pour affecter le type de classe à renvoyer.

Méthodes statiques

Vous mentionnez une méthode qui "ne connaît pas sa classe" - il s'agit d'une méthode statique en Python. Il est simplement attaché par commodité à l'objet de classe. Il pourrait éventuellement être une fonction distincte dans un autre module, mais sa signature d'appel serait la même.

Une méthode statique n'est fonction ni de la classe ni de l'objet.

Un exemple intégré d'une méthode statique est str.maketrans de Python 3.

>>> str.maketrans('abc', 'bca')
{97: 98, 98: 99, 99: 97}

Étant donné quelques arguments, il crée un dictionnaire qui n'est pas fonction de sa classe.

C'est pratique car str est toujours disponible dans l'espace de noms global, vous pouvez donc facilement l'utiliser avec la fonction translate:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Dans Python 2, vous devez y accéder depuis le module string:

>>> 'abracadabra'.translate(str.maketrans('abc', 'bca'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'str' has no attribute 'maketrans'
>>> import string
>>> 'abracadabra'.translate(string.maketrans('abc', 'bca'))
'bcrbabdbcrb'

Exemple

class AClass(object):
    """In Python, a class may have several types of methods: 
    instance methods, class methods, and static methods
    """

    def an_instance_method(self, x, y, z=None):
        """this is a function of the instance of the object
        self is the object's instance
        """
        return self.a_class_method(x, y)

    @classmethod
    def a_class_method(cls, x, y, z=None):
        """this is a function of the class of the object
        cls is the object's class
        """
        return cls.a_static_method(x, y, z=z)

    @staticmethod
    def a_static_method(x, y, z=None):
        """this is neither a function of the instance or class to 
        which it is attached
        """
        return x, y, z

Instancions:

>>> instance = AClass()

Maintenant, l'instance peut appeler toutes les méthodes:

>>> instance.an_instance_method('x', 'y')
('x', 'y', None)
>>> instance.a_static_method('x', 'y')
('x', 'y', None)
>>> instance.a_class_method('x', 'y')
('x', 'y', None)

Mais la classe n'est généralement pas destinée à appeler la méthode d'instance, bien qu'elle devrait appeler les autres:

>>> AClass.a_class_method('x', 'y')
('x', 'y', None)
>>> AClass.a_static_method('x', 'y')
('x', 'y', None)
>>> AClass.an_instance_method('x', 'y')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: an_instance_method() missing 1 required positional argument: 'y'

Vous devez passer explicitement l'instance pour appeler la méthode d'instance:

>>> AClass.an_instance_method(instance, 'x', 'y')
('x', 'y', None)
8
Aaron Hall
  • Une "méthode d'instance" est une méthode qui obtient l'objet instance comme son premier paramètre, qui par convention est appelé self. C'est la valeur par défaut.

  • Une "méthode statique" est une méthode sans le paramètre initial self. Ceci est implémenté avec le décorateur @staticmethod .

  • Une "méthode de classe" est une méthode où le paramètre initial n'est pas un objet d'instance, mais l'objet de classe ( voir cette partie de la documentation Python docs pour quoi ") objet de classe "is), qui par convention est appelé cls. Ceci est implémenté avec le décorateur @classmethod .

L'utilisation typique du terme "méthode statique" en C/C++/etc s'applique aux méthodes Python "statique" et Python "classe", car les deux de ces types de méthodes n'ont pas de référence à l'instance. En C/C++/etc, les méthodes ont normalement un accès implicite à tous les membres/méthodes non-instance de la classe, ce qui explique probablement pourquoi cette distinction n'existe que dans des langages comme Python/Ruby /etc.

4
Ixrec