136 votes

Quand dois-je utiliser @classmethod et quand la méthode def (self)?

Lors de l'intégration d'un Django app je n'ai pas utilisé avant, j'ai trouvé deux façons différentes utilisées pour définir les fonctions dans les classes. L'auteur semble utiliser à la fois très intentionnellement. Le premier est celui que j'utilise moi-même beaucoup de choses:

class Dummy(object):

    def some_function(self,*args,**kwargs):
        do something here
        self is the class instance

L'autre est un je n'ai pas l'utilisation, principalement parce que je ne comprends pas quand l'utiliser, et ce pour:

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        do something here
        cls refers to what?

Dans le Python docs de l' classmethod décorateur est expliqué avec cette phrase:

Une méthode de la classe reçoit la classe implicite premier argument, juste comme une méthode d'instance reçoit l'instance.

Donc je suppose cls désigne Dummy (les class, pas l'instance). Je n'ai pas de comprendre exactement pourquoi cela existe, parce que je pouvais toujours faire ceci:

type(self).do_something_with_the_class

Est-ce juste par souci de clarté, ou ai-je raté la partie la plus importante: effrayant et fascinant des choses qui n'a pas pu être fait sans elle?

93voto

Marcin Points 25366

Votre supposition est correcte - vous comprendre comment classmethods de travail.

La raison est que ces méthodes peuvent être appelées à la fois sur une instance OU sur la classe (dans les deux cas, l'objet de classe sera passé comme premier argument):

class Dummy(object):

    @classmethod
    def some_function(cls,*args,**kwargs):
        print cls

#both of these will have exactly the same effect
Dummy.some_function()
Dummy().some_function()

Sur l'utilisation de ces instances: Il y a au moins deux utilisations principales pour l'appel d'une classmethod sur un exemple:

  1. self.some_function() va appeler la version de some_function sur le type réel de l' self, plutôt qu'à la classe dans laquelle cet appel arrive à apparaître (et n'aurez pas besoin de l'attention si la classe est renommé); et
  2. Dans les cas où l' some_function est nécessaire pour mettre en œuvre un protocole, mais il est utile de faire appel à l'objet de classe seul.

La différence avec l' staticmethod: Il y a une autre manière de définir des méthodes qui n'ont pas accès à des données de l'instance, appelée staticmethod. Qui crée une méthode qui ne bénéficie pas d'un implicite premier argument; en conséquence, il ne sera pas adopté toutes les informations au sujet de l'instance ou de classe sur laquelle il a été appelé.

In [6]: class Foo(object): some_static = staticmethod(lambda x: x+1)

In [7]: Foo.some_static(1)
Out[7]: 2

In [8]: Foo().some_static(1)
Out[8]: 2

In [9]: class Bar(Foo): some_static = staticmethod(lambda x: x*2)

In [10]: Bar.some_static(1)
Out[10]: 2

In [11]: Bar().some_static(1)
Out[11]: 2

L'utilisation principale que j'ai trouvé pour elle est de s'adapter à une fonction existante (ce qui ne veut pas s'attendre à recevoir un self) à une méthode d'une classe (ou un objet).

-4voto

Ryan Kim Points 213

Si vous ajoutez le décorateur @classmethod, cela signifie Que vous allez faire de cette méthode en tant que méthode statique de java ou C++. ( méthode statique est un terme général , je suppose ;)) Python dispose également d' @staticmethod. et la différence entre classmethod et staticmethod est de savoir si vous pouvez l'accès à la classe ou variable statique à l'aide d'un argument ou d'un nom de classe elle-même.

class TestMethod(object):
    cls_var = 1
    @classmethod
    def class_method(cls):
        cls.cls_var += 1
        print cls.cls_var

    @staticmethod
    def static_method():
        TestMethod.cls_var += 1
        print TestMethod.cls_var
#call each method from class itself.
TestMethod.class_method()
TestMethod.static_method()

#construct instances
testMethodInst1 = TestMethod()    
testMethodInst2 = TestMethod()   

#call each method from instances
testMethodInst1.class_method()
testMethodInst2.static_method()

toutes ces classes augmentation de la cls.cls_var par 1 et de l'imprimer.

Et toutes les classes avec le même nom sur le même champ d'application, ou des instances construit avec ces classe va partager ces méthodes. Il n'y a qu'un TestMethod.cls_var et aussi il n'y a qu'un TestMethod.class_method() , TestMethod.static_method()

Et question importante. pourquoi ces méthodes seraient nécessaires.

classmethod ou staticmethod est utile lorsque vous effectuez cette classe comme une usine ou lorsque vous devez initialiser votre classe qu'une seule fois. comme d'ouvrir le fichier une fois, et en utilisant la méthode d'alimentation pour lire le fichier ligne par ligne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X