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?




@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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.