4626 Stimmen

Was ist der Unterschied zwischen @staticmethod und @classmethod in Python?

Was ist der Unterschied zwischen einer Methode dekoriert mit @staticmethod und einer Methode, die mit @classmethod dekoriert ist?

27 Stimmen

Statische Methoden sind manchmal als Funktionen auf Modulniveau in Python besser aufgehoben für die Sauberkeit. Mit einer Modulfunktion ist es einfacher, nur die Funktion zu importieren, die Sie benötigen und unnötige "."-Syntax zu vermeiden (ich sehe dich an, Objective-C). Klassenmethoden haben mehr Verwendung, da sie in Kombination mit Polymorphismus verwendet werden können, um Funktionen im "Factory Pattern" zu erstellen. Dies liegt daran, dass Klassenmethoden die Klasse als impliziten Parameter erhalten.

64 Stimmen

Tl;dr >> Im Vergleich zu normalen Methoden können statische Methoden und Klassenmethoden auch über die Klasse aufgerufen werden, aber im Gegensatz zu Klassenmethoden sind statische Methoden vererbungsfest.

9 Stimmen

Ähnlicher Vortrag von Raymond Hettinger zum Thema: youtube.com/watch?v=HTLu2DFOdTg

39voto

Laxmi Punkte 3717

Statische Methoden:

  • Einfache Funktionen ohne self-Argument.
  • Arbeiten an Klassenattributen; nicht an Instanzattributen.
  • Können sowohl über die Klasse als auch über die Instanz aufgerufen werden.
  • Die integrierte Funktion staticmethod() wird verwendet, um sie zu erstellen.

Vorteile von statischen Methoden:

  • Es lokalisiert den Funktionsnamen im Klassenbereich
  • Es verschiebt den Funktionscode näher dorthin, wo er verwendet wird
  • Bequemer zu importieren im Vergleich zu Modul-Ebene Funktionen, da jede Methode nicht speziell importiert werden muss

    @staticmethod
    def some_static_method(*args, **kwds):
        pass

Klassenmethoden:

  • Funktionen, bei denen das erste Argument der Klassenname ist.
  • Können sowohl über die Klasse als auch über die Instanz aufgerufen werden.
  • Diese werden mit der eingebauten Funktion classmethod erstellt.

     @classmethod
     def some_class_method(cls, *args, **kwds):
         pass

38voto

Jens Timmerman Punkte 8367

@Dekorateure wurden in Python 2.4 hinzugefügt. Wenn Sie Python < 2.4 verwenden, können Sie die Funktion classmethod() und staticmethod() verwenden.

Zum Beispiel, wenn Sie eine Fabrikmethode erstellen möchten (eine Funktion, die je nach Argument eine Instanz einer anderen Implementierung einer Klasse zurückgibt), können Sie etwas wie Folgendes tun:

class Cluster(object):

    def _ist_cluster_für(cls, name):
        """
        überprüfen, ob diese Klasse der Cluster mit diesem Namen ist
        dies ist ein classmethod
        """
        return cls.__name__ == name
    _ist_cluster_für = classmethod(_ist_cluster_für)

    # Statische Methode
    def getCluster(name):
        """
        statische Fabrikmethode, sollte in der Clusterklasse sein
        gibt ein Clusterobjekt für den angegebenen Namen zurück
        """
        for cls in Cluster.__subclasses__():
            if cls._ist_cluster_für(name):
                return cls()
    getCluster = staticmethod(getCluster)

Beachten Sie auch, dass dies ein gutes Beispiel für die Verwendung einer classmethod und einer statischen Methode ist. Die statische Methode gehört eindeutig zur Klasse, da sie die Klasse Cluster intern verwendet. Die classmethod benötigt nur Informationen über die Klasse und keine Instanz des Objekts.

Ein weiterer Vorteil, die Methode _ist_cluster_für zu einer classmethod zu machen, besteht darin, dass eine Unterklasse entscheiden kann, ihre Implementierung zu ändern, möglicherweise, weil sie ziemlich allgemein ist und mehr als einen Typ von Cluster handhaben kann, sodass nur die Überprüfung des Klassennamens nicht ausreichen würde.

33voto

Selva Punkte 1925

Lassen Sie mich zuerst die Ähnlichkeit zwischen einer Methode erklären, die mit @classmethod gegenüber @staticmethod dekoriert ist.

Ähnlichkeit: Beide können direkt auf die Klasse selbst aufgerufen werden, und nicht nur auf die Instanz der Klasse. Also sind beide gewissermaßen Klassenmethoden.

Unterschied: Eine Klassenmethode erhält die Klasse selbst als ersten Argument, während eine statische Methode dies nicht tut.

Also ist eine statische Methode gewissermaßen nicht an die Klasse selbst gebunden und hängt einfach dort herum, nur weil sie eine damit verbundene Funktionalität haben könnte.

>>> class Klaus:
        @classmethod
        def classmthd(*args):
            return args

        @staticmethod
        def staticmthd(*args):
            return args

# 1. classmethod ohne Argument aufrufen
>>> Klaus.classmthd()  
(__main__.Klaus,)  # die Klasse wird als erstes Argument übergeben

# 2. classmethod mit 1 Argument aufrufen
>>> Klaus.classmthd('chumma')
(__main__.Klaus, 'chumma')

# 3. statische Methode ohne Argument aufrufen
>>> Klaus.staticmthd()  
()

# 4. statische Methode mit 1 Argument aufrufen
>>> Klaus.staticmthd('chumma')
('chumma',)

0 Stimmen

Aber warum würdest du lieber das eine anstatt das andere verwenden wollen? Was ist ein echtes Anwendungsbeispiel?

30voto

Armin Ronacher Punkte 31082

@staticmethod deaktiviert lediglich die Standardfunktion als Methodenbeschreibung. classmethod wickelt Ihre Funktion in einen aufrufbaren Container ein, der eine Referenz auf die eigene Klasse als ersten Argument übergibt:

>>> class C(object):
...  pass
... 
>>> def f():
...  pass
... 
>>> staticmethod(f).__get__(None, C)

>>> classmethod(f).__get__(None, C)
>

Tatsächlich hat classmethod einen Laufzeitoverhead, ermöglicht jedoch den Zugriff auf die eigene Klasse. Alternativ empfehle ich die Verwendung einer Metaklasse und das Platzieren der Klassenmethoden auf dieser Metaklasse:

>>> class CMeta(type):
...  def foo(cls):
...   print cls
... 
>>> class C(object):
...  __metaclass__ = CMeta
... 
>>> C.foo()

1 Stimmen

Ein möglicher Nachteil einer Metaklasse für mich ist, dass Sie die Klassenmethode nicht direkt auf einer Instanz aufrufen können. c = C(); c.foo() wirft einen AttributeError, stattdessen müssten Sie type(c).foo() verwenden. Dies könnte auch als ein Feature betrachtet werden - ich kann jedoch keinen Grund dafür nennen.

26voto

zangw Punkte 36978

Der definitive Leitfaden zur Verwendung von statischen, Klassen- oder abstrakten Methoden in Python ist ein guter Link zu diesem Thema und fasst es wie folgt zusammen.

@staticmethod Funktion ist nichts anderes als eine Funktion, die innerhalb einer Klasse definiert ist. Sie kann aufgerufen werden, ohne zuerst die Klasse zu instanziieren. Ihre Definition ist unveränderlich durch Vererbung.

  • Python muss keine gebundenen Methoden für Objekte instanziieren.
  • Es erleichtert die Lesbarkeit des Codes und hängt nicht vom Zustand des Objekts selbst ab;

@classmethod Funktion kann auch ohne Instanziierung der Klasse aufgerufen werden, aber ihre Definition folgt der Unterklasse, nicht der Elternklasse, durch Vererbung, kann von der Unterklasse überschrieben werden. Das liegt daran, dass das erste Argument für die @classmethod Funktion immer cls (Klasse) sein muss.

  • Factory-Methoden, die verwendet werden, um eine Instanz für eine Klasse zu erstellen, zum Beispiel unter Verwendung einer Art von Vorverarbeitung.
  • Statische Methoden, die statische Methoden aufrufen: Wenn Sie eine statische Methode in mehrere statische Methoden aufteilen, sollten Sie den Klassennamen nicht fest codieren, sondern Klassenmethoden verwenden.

0 Stimmen

Vielen Dank, @zangw - die vererbte Unveränderlichkeit der statischen Funktion ist der Schlüsselunterschied, anscheinend.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X