@staticmethod vs. @classmethod in Python

Lesezeit: 7 Minuten

Daryl Spitzers Benutzeravatar
Daryl Spitzer

Was ist der Unterschied zwischen einer Methode dekoriert mit @staticmethod und eines verziert mit @classmethod?

  • Aus Gründen der Sauberkeit sind statische Methoden manchmal besser geeignet als Funktionen auf Modulebene in Python. Mit einer Modulfunktion ist es einfacher, genau die Funktion zu importieren, die Sie benötigen, und unnötige „.“ zu vermeiden. Syntax (ich spreche von Objective-C). Klassenmethoden haben einen größeren Nutzen, da sie in Kombination mit Polymorphismus verwendet werden können, um „Fabrikmuster“-Funktionen zu erstellen. Dies liegt daran, dass Klassenmethoden die Klasse als impliziten Parameter empfangen.

    – Faust der Wut

    6. Dezember 2017 um 3:44

  • tl;dr >> Im Vergleich zu normalen Methoden kann auf die statischen Methoden und Klassenmethoden auch über die Klasse zugegriffen werden, aber im Gegensatz zu Klassenmethoden sind statische Methoden durch Vererbung unveränderlich.

    – Herr Unnormalized Posterior

    11. Juli 2018 um 15:02 Uhr


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

    – moooeeeep

    10. September 2018 um 9:35 Uhr

Benutzer-Avatar von Thomas Wouters
Thomas Wouters

A statische Methode ist eine Methode, die nichts über die Klasse oder Instanz weiß, für die sie aufgerufen wurde. Es werden lediglich die übergebenen Argumente abgerufen, kein implizites erstes Argument. In Python ist es grundsätzlich nutzlos – Sie können einfach eine Modulfunktion anstelle einer statischen Methode verwenden.

A Klassenmethodehingegen ist eine Methode, der die Klasse, für die sie aufgerufen wurde, oder die Klasse der Instanz, für die sie aufgerufen wurde, als erstes Argument übergeben wird. Dies ist nützlich, wenn Sie möchten, dass die Methode eine Factory für die Klasse ist: Da sie als erstes Argument die tatsächliche Klasse erhält, für die sie aufgerufen wurde, können Sie immer die richtige Klasse instanziieren, selbst wenn Unterklassen beteiligt sind. Beobachten Sie zum Beispiel, wie dict.fromkeys()eine Klassenmethode, gibt eine Instanz der Unterklasse zurück, wenn sie für eine Unterklasse aufgerufen wird:

>>> class DictSubclass(dict):
...     def __repr__(self):
...         return "DictSubclass"
... 
>>> dict.fromkeys("abc")
{'a': None, 'c': None, 'b': None}
>>> DictSubclass.fromkeys("abc")
DictSubclass
>>> 

  • Eine statische Methode ist nicht nutzlos – sie ist eine Möglichkeit, eine Funktion in eine Klasse einzufügen (weil sie logisch dorthin gehört) und gleichzeitig anzugeben, dass sie keinen Zugriff auf die Klasse erfordert.

    – Tony Meyer

    26. September 2008 um 10:10

  • Daher nur „im Grunde“ nutzlos. Eine solche Organisation sowie die Abhängigkeitsinjektion sind gültige Anwendungen von staticmethods, aber da Module und nicht Klassen wie in Java die Grundelemente der Codeorganisation in Python sind, ist ihre Verwendung und Nützlichkeit selten.

    – Thomas Wouters

    26. September 2008 um 13:40 Uhr

  • Was ist logisch daran, eine Methode innerhalb einer Klasse zu definieren, wenn sie weder mit der Klasse noch mit ihren Instanzen etwas zu tun hat?

    – Ben James

    12. März 2010 um 9:11 Uhr


  • Vielleicht aus Erbschaftsgründen? Statische Methoden können genau wie Instanzmethoden und Klassenmethoden vererbt und überschrieben werden, und die Suche funktioniert wie erwartet (anders als in Java). Statische Methoden werden nicht wirklich statisch aufgelöst, unabhängig davon, ob sie für die Klasse oder die Instanz aufgerufen werden. Daher besteht der einzige Unterschied zwischen Klassen- und statischen Methoden im impliziten ersten Argument.

    – haridsv

    8. April 2010 um 1:32

  • Sie schaffen außerdem einen übersichtlicheren Namespace und machen es einfacher zu verstehen, dass die Funktion etwas mit der Klasse zu tun hat.

    – Imbrondir

    22. August 2011 um 11:58

Benutzeravatar von Du D
Du D.

Um zu entscheiden, ob verwendet werden soll @staticmethod oder @classmethod Sie müssen in Ihre Methode hineinschauen. Wenn Ihre Methode auf andere Variablen/Methoden in Ihrer Klasse zugreift, verwenden Sie @classmethod. Wenn Ihre Methode hingegen keine anderen Teile der Klasse berührt, verwenden Sie @staticmethod.

class Apple:

    _counter = 0

    @staticmethod
    def about_apple():
        print('Apple is good for you.')

        # note you can still access other member of the class
        # but you have to use the class instance 
        # which is not very nice, because you have repeat yourself
        # 
        # For example:
        # @staticmethod
        #    print('Number of apples have been juiced: %s' % Apple._counter)
        #
        # @classmethod
        #    print('Number of apples have been juiced: %s' % cls._counter)
        #
        #    @classmethod is especially useful when you move your function to another class,
        #       you don't have to rename the referenced class 

    @classmethod
    def make_apple_juice(cls, number_of_apples):
        print('Making juice:')
        for i in range(number_of_apples):
            cls._juice_this(i)

    @classmethod
    def _juice_this(cls, apple):
        print('Juicing apple %d...' % apple)
        cls._counter += 1

  • Was wäre der Vorteil von classmethod und cls._counter gegenüber staticmethod und Apple._counter?

    – Robert Nowak

    11. Okt. 2019 um 10:38

  • cls._counter wäre es immer noch cls._counter auch wenn der Code in eine andere Klasse eingefügt oder der Klassenname geändert wird. Apple._counter ist spezifisch für die Apple Klasse; Für eine andere Klasse oder wenn der Klassenname geändert wird, müssten Sie die referenzierte Klasse ändern.

    – apaderno

    12. November 2019 um 22:55 Uhr

  • Ich hoffe, mit „verschieben“ meinst du nicht „kopieren“, lol

    – Zachja

    23. November 2022 um 21:38 Uhr

  • Warum man sich in diesem Fall überhaupt um den Dekorateur kümmert, wird aus Ihrer Beschreibung nicht wirklich klar

    – Mehdi

    9. März um 14:02 Uhr

Benutzeravatar von me_and
ich und

Offizielle Python-Dokumente:

@classmethod

Eine Klassenmethode empfängt die Klasse als implizites erstes Argument, genau wie eine Instanzmethode die Instanz empfängt. Um eine Klassenmethode zu deklarieren, verwenden Sie diese Redewendung:

class C:
    @classmethod
    def f(cls, arg1, arg2, ...): ... 

Der @classmethod Form ist eine Funktion
Dekorateur – siehe Beschreibung der Funktionsdefinitionen in Funktionsdefinitionen für Details.

Es kann entweder für die Klasse aufgerufen werden (z. B C.f()) oder auf einer Instanz (z. B C().f()). Die Instanz wird bis auf ihre Klasse ignoriert. Wenn eine Klassenmethode für eine abgeleitete Klasse aufgerufen wird, wird das abgeleitete Klassenobjekt als implizites erstes Argument übergeben.

Klassenmethoden unterscheiden sich von statischen C++- oder Java-Methoden. Wenn Sie diese wollen, sehen Sie staticmethod() in diesem Abschnitt.

@staticmethod

Eine statische Methode erhält kein implizites erstes Argument. Um eine statische Methode zu deklarieren, verwenden Sie diese Redewendung:

class C:
    @staticmethod
    def f(arg1, arg2, ...): ... 

Der @staticmethod Form ist eine Funktion
Dekorateur – siehe Beschreibung der Funktionsdefinitionen in Funktionsdefinitionen für Details.

Es kann entweder für die Klasse aufgerufen werden (z. B C.f()) oder auf einer Instanz (z. B C().f()). Die Instanz wird bis auf ihre Klasse ignoriert.

Statische Methoden in Python ähneln denen in Java oder C++. Ein fortgeschritteneres Konzept finden Sie unter
classmethod() in diesem Abschnitt.

  • Was wäre der Vorteil von classmethod und cls._counter gegenüber staticmethod und Apple._counter?

    – Robert Nowak

    11. Okt. 2019 um 10:38

  • cls._counter wäre es immer noch cls._counter auch wenn der Code in eine andere Klasse eingefügt oder der Klassenname geändert wird. Apple._counter ist spezifisch für die Apple Klasse; Für eine andere Klasse oder wenn der Klassenname geändert wird, müssten Sie die referenzierte Klasse ändern.

    – apaderno

    12. November 2019 um 22:55 Uhr

  • Ich hoffe, mit „verschieben“ meinst du nicht „kopieren“, lol

    – Zachja

    23. November 2022 um 21:38 Uhr

  • Warum man sich in diesem Fall überhaupt um den Dekorateur kümmert, wird aus Ihrer Beschreibung nicht wirklich klar

    – Mehdi

    9. März um 14:02 Uhr

Benutzeravatar der Community
Gemeinschaft

Hier ist ein kurzer Artikel zu dieser Frage

Die @staticmethod-Funktion ist nichts anderes als eine innerhalb einer Klasse definierte Funktion. Es ist aufrufbar, ohne die Klasse zuerst zu instanziieren. Seine Definition ist durch Vererbung unveränderlich.

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

  • Bedeutet das also, dass ich durch die Verwendung einer statischen Methode immer an die übergeordnete Klasse und mit der Klassenmethode an die Klasse gebunden bin, in der ich die Klassenmethode deklariere (in diesem Fall die Unterklasse)?

    – Mohan Gulati

    3. November 2009 um 19:06 Uhr

  • Nein. Durch die Verwendung einer statischen Methode sind Sie überhaupt nicht gebunden; Es gibt keinen impliziten ersten Parameter. Durch die Verwendung von classmethod erhalten Sie als impliziten ersten Parameter die Klasse, für die Sie die Methode aufgerufen haben (wenn Sie sie direkt für eine Klasse aufgerufen haben), oder die Klasse der Instanz, für die Sie die Methode aufgerufen haben (wenn Sie sie für eine Instanz aufgerufen haben).

    – Matt Anderson

    3. November 2009 um 19:18

  • Könnte etwas erweitert werden, um zu zeigen, dass Klassenmethoden durch die Verwendung einer Klasse als erstes Argument direkten Zugriff auf andere Klassenattribute und -methoden haben, statische Methoden jedoch nicht (dafür müssten sie MyClass.attr fest codieren).

    – MestreLion

    3. Mai 2012 um 10:01


  • „Seine Definition ist durch Vererbung unveränderlich.“ macht in Python keinen Sinn, Sie können eine statische Methode problemlos überschreiben.

    – cz

    17. September 2019 um 15:20 Uhr

1454750cookie-check@staticmethod vs. @classmethod in Python

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy