Das Objekt 'staticmethod' kann nicht aufgerufen werden

74

Ich habe diesen Code:

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open,
        2: proccess,   
        }

obj = A.switch[1]()

Wenn ich dies ausführe, erhalte ich immer wieder den Fehler:

TypeError: 'staticmethod' object is not callable

wie man es löst?

Ramin Farajpour Cami
quelle
Mögliches Duplikat des Objekts 'classmethod' kann nicht aufgerufen werden
Melpomene
@melpomene: Ups, ich bin mir nicht sicher, warum ich das verpasst habe.
Martijn Pieters
@melpomene: nicht ganz ein Betrüger, Sie haben verschiedene (mehr) Optionen mit staticmethodObjekten.
Martijn Pieters
@MartijnPieters Oh, ich habe nicht ganz bemerkt, dass der Fragentitel nicht mit der Fehlermeldung im Text übereinstimmt.
Melpomene

Antworten:

94

Sie speichern ungebundene staticmethod Objekte in einem Wörterbuch. Solche Objekte (sowie classmethodObjekte, Funktionen und propertyObjekte) werden nur durch das Deskriptorprotokoll gebunden , indem auf den Namen als Attribut für die Klasse oder eine Instanz zugegriffen wird. Der direkte Zugriff auf die staticmethodObjekte im Klassenkörper ist kein Attributzugriff.

Erstellen Sie das Wörterbuch entweder nach dem Erstellen der Klasse (damit Sie als Attribute darauf zugreifen können) oder binden Sie es explizit oder extrahieren Sie die ursprüngliche Funktion, bevor Sie sie im Wörterbuch speichern.

Beachten Sie, dass "Bindung" für staticmethodObjekte lediglich bedeutet, dass der Kontext lediglich ignoriert wird. Eine Grenze staticmethodgibt die zugrunde liegende Funktion unverändert zurück.

Sie können also das Wörterbuch aufheben und das Deskriptorprotokoll mithilfe von Attributen auslösen:

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

A.switch = {
    1: A.open,
    2: A.proccess,   
}

oder explizit zu binden, indem ein Dummy-Kontext übergeben wird (der sowieso ignoriert wird):

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open.__get__(object),
        2: proccess.__get__(object),   
    }

oder greifen Sie direkt mit dem __func__Attribut auf die zugrunde liegende Funktion zu :

class A(object):
    @staticmethod
    def open():
        return 123
    @staticmethod
    def proccess():
        return 456

    switch = {
        1: open.__func__,
        2: proccess.__func__,   
    }

Wenn Sie jedoch nur versuchen, einen Namespace für eine Reihe von Funktionen bereitzustellen , sollten Sie zunächst kein Klassenobjekt verwenden. Stellen Sie die Funktionen in ein Modul . Auf diese Weise müssen Sie überhaupt keine staticmethodDekorateure verwenden und diese nicht erneut auspacken.

Martijn Pieters
quelle
13
Der Hinweis am Ende ist der wichtigste Teil, IMO. Wir können einfach eine Liste aller Funktionen erstellen, die wir von einem Modul erwarten, und sie in einer Schleife aufrufen.
Azim