2017 Stimmen

Statische Methoden in Python?

Ist es möglich, statische Methoden in Python zu haben, die ich aufrufen könnte, ohne eine Klasse zu initialisieren, wie:

ClassName.static_method()

2279voto

dbr Punkte 158949

Ja, mit dem staticmethod Tapezierer

class MyClass(object):
    @staticmethod
    def the_static_method(x):
        print(x)

MyClass.the_static_method(2)  # outputs 2

Beachten Sie, dass einige Codes die alte Methode der Definition einer statischen Methode verwenden können, indem sie staticmethod als Funktion und nicht als Dekorator. Dies sollte nur verwendet werden, wenn Sie alte Versionen von Python unterstützen müssen (2.2 und 2.3)

class MyClass(object):
    def the_static_method(x):
        print(x)
    the_static_method = staticmethod(the_static_method)

MyClass.the_static_method(2)  # outputs 2

Dies ist völlig identisch mit dem ersten Beispiel (mit @staticmethod ), nur nicht mit der schönen Dekorator-Syntax

Schließlich verwenden Sie staticmethod sparsam! Es gibt nur sehr wenige Situationen, in denen statische Methoden in Python notwendig sind, und ich habe sie schon oft dort eingesetzt gesehen, wo eine separate "Top-Level"-Funktion klarer gewesen wäre.


Der folgende Text ist ein Auszug aus der Dokumentation: :

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

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

Die @staticmethod-Form ist eine Funktion Tapezierer - siehe die Beschreibung der Funktionsdefinitionen in Funktionsdefinitionen für Einzelheiten.

Sie kann entweder in der Klasse aufgerufen werden (z. B. C.f() ) oder auf eine Instanz (z. B. C().f() ). Die Instanz wird mit Ausnahme ihrer Klasse ignoriert.

Statische Methoden in Python sind denen in Java oder C++ ähnlich. Für ein fortgeschritteneres Konzept siehe classmethod() .

Weitere Informationen zu statischen Methoden finden Sie in der Dokumentation zur Standardtyphierarchie in Die Standard-Typenhierarchie .

Neu in Version 2.2.

Geändert in Version 2.4: Funktionsdekorator-Syntax hinzugefügt.

28 Stimmen

Warum das Hinzufügen @staticmethod Dekoration oder die Verwendung eines Funktionszeigers, wenn man den ersten Schritt einfach vermeiden kann self Parameter? Nun, für ein Objekt a werden Sie nicht anrufen können a.your_static_method() was in anderen Sprachen erlaubt ist, aber trotzdem als schlechte Praxis angesehen wird und der Compiler immer davor warnt

1 Stimmen

Ich verwende Python 2.7.12, mit @staticmethod decorator bin ich nicht in der Lage, die erste definierte statische Methode aufzurufen. Es gibt einen Fehler: TypeError: Das Objekt 'staticmethod' ist nicht aufrufbar

0 Stimmen

Supratim Samantray, sind Sie sicher? aquí Es ist eindeutig festgelegt, dass es nach 2.4 verwendet werden kann.

256voto

Richard Ambler Punkte 4293

Ich denke, dass Steven hat tatsächlich Recht . Um die ursprüngliche Frage zu beantworten: Um eine Klassenmethode einzurichten, gehen Sie einfach davon aus, dass das erste Argument keine aufrufende Instanz sein wird, und stellen Sie dann sicher, dass Sie die Methode nur von der Klasse aus aufrufen.

(Beachten Sie, dass sich diese Antwort auf Python 3.x bezieht. In Python 2.x erhalten Sie eine TypeError für den Aufruf der Methode in der Klasse selbst).

Zum Beispiel:

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    def rollCall(n): #this is implicitly a class method (see comments below)
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)

In diesem Code geht die Methode "rollCall" davon aus, dass das erste Argument keine Instanz ist (wie es der Fall wäre, wenn sie von einer Instanz statt von einer Klasse aufgerufen würde). Solange "rollCall" von der Klasse und nicht von einer Instanz aufgerufen wird, funktioniert der Code einwandfrei. Wenn wir versuchen, "rollCall" von einer Instanz aus aufzurufen, z. B.:

rex.rollCall(-1)

würde jedoch eine Ausnahme ausgelöst werden, da zwei Argumente gesendet würden: sich selbst und -1, und "rollCall" ist nur für ein Argument definiert.

Übrigens würde rex.rollCall() die richtige Anzahl von Argumenten senden, aber auch eine Ausnahme auslösen, weil n jetzt eine Hundeinstanz (d.h. rex) darstellen würde, obwohl die Funktion erwartet, dass n numerisch ist.

Hier kommt die Dekoration ins Spiel: Wenn wir der Methode "rollCall" vorangestellt haben

@staticmethod

dann können wir sie sogar von einer Instanz aus aufrufen, indem wir ausdrücklich angeben, dass die Methode statisch ist. Jetzt,

rex.rollCall(-1)

funktionieren würde. Das Einfügen von @staticmethod vor einer Methodendefinition verhindert also, dass eine Instanz sich selbst als Argument sendet.

Sie können dies überprüfen, indem Sie den folgenden Code mit und ohne die auskommentierte @staticmethod-Zeile ausprobieren.

class Dog:
    count = 0 # this is a class variable
    dogs = [] # this is a class variable

    def __init__(self, name):
        self.name = name #self.name is an instance variable
        Dog.count += 1
        Dog.dogs.append(name)

    def bark(self, n): # this is an instance method
        print("{} says: {}".format(self.name, "woof! " * n))

    @staticmethod
    def rollCall(n):
        print("There are {} dogs.".format(Dog.count))
        if n >= len(Dog.dogs) or n < 0:
            print("They are:")
            for dog in Dog.dogs:
                print("  {}".format(dog))
        else:
            print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))

fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)

8 Stimmen

Das erste Beispiel (Aufruf durch Klasse ohne @staticmethod) funktioniert bei mir unter Python 2.7 nicht. Ich erhalte "TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)".

2 Stimmen

Das funktioniert nicht. Sowohl Dog.rollCall(-1) als auch rex.rollCall(-1) geben das gleiche zurück TypeError: unbound method rollCall() must be called with Dog instance as first argument (got int instance instead)

6 Stimmen

@MestreLion Ich glaube nicht, dass dies ein großer Vorteil ist, da es nur statische und Instanzmethoden durcheinander bringt und das eine wie das andere aussehen lässt. Wenn man weiß, dass eine Methode statisch ist, sollte man sie als statische Methode aufrufen. Die Tatsache, dass die Methode Ihre Instanz nicht benötigt oder verwendet, sollte selbstverständlich sein, wo immer Sie die Methode verwenden. Ich verwende immer T.my_static_method() o type(my_t_instance).my_static_method() , da dies klarer ist und sofort deutlich macht, dass ich eine statische Methode aufrufe.

92voto

Paolo Bergantino Punkte 465120

Ja, sehen Sie sich die staticmethod Dekorateur:

>>> class C:
...     @staticmethod
...     def hello():
...             print "Hello World"
...
>>> C.hello()
Hello World

1 Stimmen

Viele der obigen Antworten wurden heruntergestuft, weil sie nur ein Beispiel liefern. Warum ist dies anders?

66voto

Sie müssen nicht unbedingt die @staticmethod Dekorateur. Man deklariert einfach eine Methode (die nicht den Parameter self erwartet) und ruft sie von der Klasse aus auf. Der Dekorator ist nur für den Fall da, dass Sie die Methode auch von einer Instanz aus aufrufen wollen (was Sie nicht wollten)

Meistens verwendet man aber nur Funktionen...

0 Stimmen

Dies würde nicht für Python 2.5.2 funktionieren class Dummy: def static1(): print "hello from static1" @staticmethod def static2(): print "hello from static2" Dummy.static2() Dummy.static1() Ausgabe: hallo von static2 Traceback<letzter Aufruf>: File "ll.py", line 46, in <module> Dummy.static1() TypeError: unbound method static1() must be called with Dummy instance as first argument (got nothing instead)

7 Stimmen

Dies funktioniert nicht innerhalb einer Klasse. Python übergibt self als erstes Argument, es sei denn, Sie weisen es an, dies nicht zu tun. (siehe: decorator)

9 Stimmen

Eigentlich ist dies in 2.7 falsch und ab 3.X legal (in 3.2 gut getestet). Das heißt, Sie kann nicht eine Methode aus dem Kontext einer Klasse ohne den @staticmethod Dekorator in 2.7 und darunter aufrufen. In 3.2 funktioniert es und fügt eine self je nach Aufforderung entsprechend. Testfall: pastebin.com/12DDV7DB .

35voto

Statische Methoden in Python?

Ist es möglich, statische Methoden in Python zu haben, so dass ich sie aufrufen kann ohne eine Klasse zu initialisieren, wie:

ClassName.StaticMethod()

Ja, statische Methoden können auf diese Weise erstellt werden (obwohl es ein bisschen mehr Pythonisch Unterstriche anstelle von CamelCase für Methoden zu verwenden):

class ClassName(object):

    @staticmethod
    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

Das obige Beispiel verwendet die Dekorator-Syntax. Diese Syntax ist äquivalent zu

class ClassName(object):

    def static_method(kwarg1=None):
        '''return a value that is a function of kwarg1'''

    static_method = staticmethod(static_method)

Dies kann genau so verwendet werden, wie Sie es beschrieben haben:

ClassName.static_method()

Ein eingebautes Beispiel für eine statische Methode ist str.maketrans() in Python 3, die eine Funktion in der string Modul in Python 2.


Eine weitere Option, die wie von Ihnen beschrieben verwendet werden kann, ist die classmethod Der Unterschied besteht darin, dass die Klassenmethode die Klasse als implizites erstes Argument erhält, und wenn sie unterklassig ist, erhält sie die Unterklasse als implizites erstes Argument.

class ClassName(object):

    @classmethod
    def class_method(cls, kwarg1=None):
        '''return a value that is a function of the class and kwarg1'''

Beachten Sie, dass cls ist kein erforderlicher Name für das erste Argument, aber die meisten erfahrenen Python-Programmierer werden es für schlecht gemacht halten, wenn Sie etwas anderes verwenden.

Diese werden in der Regel als alternative Konstrukteure verwendet.

new_instance = ClassName.class_method()

Ein eingebautes Beispiel ist dict.fromkeys() :

new_dict = dict.fromkeys(['key1', 'key2'])

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