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

8voto

Nicolae Petridean Punkte 566

Eine Klassenmethode erhält die Klasse als implizites erstes Argument, genauso wie eine Instanzmethode die Instanz erhält. Es handelt sich um eine Methode, die an die Klasse gebunden ist und nicht an das Objekt der Klasse. Sie hat Zugriff auf den Zustand der Klasse, da sie einen Klassenparameter erhält, der auf die Klasse und nicht auf die Objektinstanz zeigt. Sie kann den Zustand einer Klasse ändern, der auf alle Instanzen der Klasse angewendet wird. Zum Beispiel kann sie eine Klassenvariable ändern, die auf alle Instanzen anwendbar ist.

Auf der anderen Seite erhält eine statische Methode im Vergleich zu Klassenmethoden oder Instanzmethoden kein implizites erstes Argument. Sie kann nicht auf den Klassenstatus zugreifen oder ihn ändern. Sie gehört ausschließlich zur Klasse, weil das aus gestalterischer Sicht der richtige Weg ist. In Bezug auf die Funktionalität ist sie jedoch zur Laufzeit nicht an die Klasse gebunden.

Als Richtlinie sollten statische Methoden als Hilfsprogramme verwendet werden, Klassenmethoden beispielsweise als Fabrik. Oder vielleicht zur Definition eines Singleton. Und Instanzmethoden sollten verwendet werden, um den Zustand und das Verhalten von Instanzen zu modellieren.

Hoffentlich war ich klar!

7voto

Michael Swartz Punkte 823

Mein Beitrag zeigt den Unterschied zwischen @classmethod, @staticmethod und Instanzmethoden auf, einschließlich der Art und Weise, wie eine Instanz indirekt eine @staticmethod aufrufen kann. Anstatt jedoch eine @staticmethod indirekt von einer Instanz aus aufzurufen, ist es möglicherweise "pythonischer", sie privat zu machen. Hier wird zwar nicht gezeigt, wie man etwas aus einer privaten Methode erhält, aber es handelt sich im Grunde um dasselbe Konzept.

#!python3

from os import system
system('cls')
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

class DemoClass(object):
    # Instanzmethoden benötigen eine Klasseninstanz und können über 'self' auf die Instanz zugreifen
    def instance_method_1(self):
        return 'wird von innen der instance_method_1() aufgerufen'

    def instance_method_2(self):
        # Eine Instanz außerhalb der Klasse ruft indirekt die static_method auf
        return self.static_method() + ' über instance_method_2()'

    # Klassenmethoden benötigen keine Klasseninstanz, sie können nicht auf die
    # Instanz (self) zugreifen, haben aber Zugriff auf die Klasse selbst über 'cls'
    @classmethod
    def class_method(cls):
        return 'wird von innen der class_method() aufgerufen'

    # Statische Methoden haben keinen Zugriff auf 'cls' oder 'self', sie funktionieren wie
    # normale Funktionen, gehören aber zum Namespace der Klasse
    @staticmethod
    def static_method():
        return 'wird von innen der static_method() aufgerufen'
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# Funktioniert auch, wenn die Klasse nicht instanziiert wurde
print(DemoClass.class_method() + '\n')
''' wird von innen der class_method() aufgerufen '''

# Funktioniert auch, wenn die Klasse nicht instanziiert wurde
print(DemoClass.static_method() + '\n')
''' wird von innen der static_method() aufgerufen '''
# %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %   %

# >>>>> Alle Arten von Methoden können auf einer Klasseninstanz aufgerufen werden <<<<<
# Instanziierung der Klasse
democlassObj = DemoClass()

# Aufruf von instance_method_1()
print(democlassObj.instance_method_1() + '\n')
''' wird von innen der instance_method_1() aufgerufen '''

# # Indirekter Aufruf von static_method durch instance_method_2(), dies ist wirklich nicht sinnvoll,
# da eine @staticmethod aufgerufen werden kann, ob die Klasse instanziiert wurde oder nicht
print(democlassObj.instance_method_2() + '\n')
''' wird von innen der static_method() über instance_method_2() aufgerufen '''

# Aufruf von class_method()
print(democlassObj.class_method() + '\n')
'''  wird von innen der class_method() aufgerufen '''

# Aufruf von static_method()
print(democlassObj.static_method())
''' wird von innen der static_method() aufgerufen '''

"""
# Ob die Klasse instanziiert wurde oder nicht, das funktioniert nicht
print(DemoClass.instance_method_1() + '\n')
'''
TypeError: TypeError: nicht gebundene Methode instancemethod() muss mit
DemoClass-Instanz als erstes Argument aufgerufen werden (anstatt nichts zu erhalten)
'''
"""

7voto

David Schumann Punkte 11281

Sie sollten den Unterschied zwischen folgendem in Betracht ziehen:

class A:
    def foo():  # kein self-Parameter, kein Dekorator
        pass

und

class B:
    @staticmethod
    def foo():  # kein self-Parameter
        pass

Dies hat sich zwischen Python2 und Python3 geändert:

Python2:

>>> A.foo()
TypeError
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

Python3:

>>> A.foo()
>>> A().foo()
TypeError
>>> B.foo()
>>> B().foo()

Die Verwendung von @staticmethod für Methoden, die nur direkt von der Klasse aufgerufen werden, ist in Python3 optional geworden. Wenn Sie sie sowohl von der Klasse als auch von der Instanz aus aufrufen möchten, müssen Sie immer noch den @staticmethod Dekorator verwenden.

Andere Fälle wurden bereits von unutbus Antwort gut behandelt.

7voto

vijay Punkte 109

@classmethod: kann verwendet werden, um einen gemeinsamen globalen Zugriff auf alle Instanzen zu schaffen, die von dieser Klasse erstellt wurden..... wie das Aktualisieren eines Datensatzes durch mehrere Benutzer.... Ich fand es besonders nützlich, als ich Singleton erstellte..:)

@static method: hat nichts mit der Klasse oder der zugehörigen Instanz zu tun... aber zur besseren Lesbarkeit kann static method verwendet werden

4voto

Jacky1205 Punkte 2981

Ich denke, dass eine rein Python-Version von staticmethod und classmethod dazu beitragen würde, den Unterschied zwischen ihnen auf Sprachebene zu verstehen (siehe Descriptor-Howto-Guide).

Beide sind Nicht-Daten-Deskriptoren (Es wäre einfacher, sie zu verstehen, wenn Sie zuerst mit Deskriptoren vertraut sind).

class StaticMethod(object):
    "Emuliere PyStaticMethod_Type() in Objects/funcobject.c"

    def __init__(self, f):
        self.f = f

    def __get__(self, obj, objtype=None):
        return self.f

class ClassMethod(object):
    "Emuliere PyClassMethod_Type() in Objects/funcobject.c"
    def __init__(self, f):
        self.f = f

    def __get__(self, obj, cls=None):
        def inner(*args, **kwargs):
            if cls is None:
                cls = type(obj)
            return self.f(cls, *args, **kwargs)
        return inner

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