50

Bei der Integration einer Django-App, die ich noch nicht benutzt habe, habe ich zwei verschiedene Möglichkeiten gefunden, Funktionen in Klassen zu definieren. Der Autor scheint sie beide sehr bewusst zu benutzen. Die erste ist, den ich mir selbst eine Menge verwenden:Wann sollte ich @classmethod und wann def-Methode (self) verwenden?

class Dummy(object): 

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

Das andere ist, die ich nicht verwenden, vor allem, weil ich nicht verstehe, wenn es zu benutzen, und was für:

class Dummy(object): 

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

in dem Python docs wird die classmethod decorator mit diesem Satz erklärt:

Eine Klassenmethode erhält die Klasse als implizites erstes Argument, nur wie eine Instanzmethode die Instanz empfängt.

Also ich denke, cls zu Dummy bezieht sich selbst (die class, nicht die Instanz). Ich verstehe nicht genau, warum dies existiert, weil ich immer dies tun könnte:

type(self).do_something_with_the_class 

Dies ist nur aus Gründen der Klarheit, oder habe ich den wichtigsten Teil verpassen: spooky und faszinierende Dinge, die nicht sein könnten fertig ohne es?

Antwort

47

Ihre Schätzung ist richtig - Sie verstehen wie s arbeiten.

Der Grund ist, dass diese Methoden sowohl auf eine Instanz oder auf der Klasse aufgerufen werden kann (in beiden Fällen wird die Klasse Objekt als erstes Argument übergeben werden):

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() 

Auf den Einsatz von diese auf Instanzen: Es gibt mindestens zwei Hauptverwendungszwecke für einen Class auf einer Instanz anrufen:

  1. self.some_function() wird die Version von some_function auf der tatsächlichen Art von self nennen, anstatt die cla s, in dem dieser Aufruf auftritt (und benötigt keine Aufmerksamkeit, wenn die Klasse umbenannt wird); und
  2. In Fällen, in denen some_function erforderlich ist, um ein Protokoll zu implementieren, ist aber nützlich, das Klassenobjekt allein aufzurufen.

Der Unterschied staticmethod: Es gibt eine weitere Möglichkeit, Methoden zu definieren, die, genannt staticmethod nicht Instanzdaten zugreifen. Dies erzeugt eine Methode, die überhaupt kein implizites erstes Argument erhält; dementsprechend werden keine Informationen über die Instanz oder Klasse, an der sie aufgerufen wurde, weitergegeben.

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 

Die Hauptanwendung ich es gefunden habe, ist eine vorhandene Funktion anzupassen (was erwartet nicht ein self zu erhalten), um eine Methode für eine Klasse (oder Objekt).

+1

Nice one: Ich mag die Aufteilung der Antwort in wie - warum. Soweit ich es jetzt verstanden habe, erlaubt @classmethod den Zugriff auf die Funktion, ohne dass eine Instanz benötigt wird. Genau das habe ich gesucht, danke. – marue

+0

@marue Gern geschehen! – Marcin

+0

Ich würde sagen, Aufruf von Klassenmethoden auf Instanzen ist schlechte Codierung Stil - nur kein Grund, dies zu tun und kann nur zu Verwirrung führen. Aber ja, es funktioniert (Java erlaubt das Gleiche, gibt aber eine Kompilierungswarnung aus, wenn statische Methoden durch Instanzen aufgerufen werden) – Voo

0

Wenn Sie Decorator @classmethod hinzufügen, bedeutet das, dass Sie diese Methode als statische Methode von Java oder C++ machen.(statische Methode ist ein allgemeiner Begriff ich denke ;)) Python hat auch @staticmethod. und Unterschied zwischen Klassenmethode und staticmethod ist, ob Sie Zugriff auf Klasse oder statische Variable mit Argument oder Klassenname selbst.

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() 

alle diese Klassen erhöhen cls.cls_var um 1 und drucken es.

Und alle Klassen, die denselben Namen für denselben Bereich oder dieselben Instanzen verwenden, die mit dieser Klasse erstellt wurden, teilen diese Methoden. Es gibt nur einen TestMethod.cls_var und auch gibt es nur eine TestMethod.class_method(), TestMethod.static_method()

und wichtige Frage. warum diese Methode benötigt würde.

Class oder static ist nützlich, wenn Sie diese Klasse als Fabrik machen oder wenn Sie Ihre Klasse nur einmal initialisieren. Öffnen Sie die Datei einmal und verwenden Sie die Feed-Methode, um die Datei Zeile für Zeile zu lesen.

+1

(a) Statische Methoden sind etwas anderes; (b) Klassenmethoden werden nicht von jeder Klasse geteilt. – Marcin

+0

@Marcin Danke, dass du mir meine unklaren Definitionen und all das mitteilst. –

Verwandte Themen