“静态方法”对象不可调用


77

我有这个代码:

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

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

obj = A.switch[1]()

运行此命令时,我不断收到错误消息:

TypeError: 'staticmethod' object is not callable

怎么解决呢?




@melpomene:糟糕,我不确定为什么错过了。
马丁·彼得斯

@melpomene:不完全是一个骗子,您对staticmethod对象有不同的(更多)选择。
马丁·皮特斯

@MartijnPieters哦,我还没有意识到问题标题与正文中的错误消息不匹配。
melpomene

Answers:


96

您正在将未绑定的 staticmethod对象存储在字典中。通过访问名称作为类或实例上的属性,此类对象(以及classmethod对象,函数和property对象)仅通过描述符协议进行绑定。直接访问staticmethod类主体中的对象不是属性访问。

创建类之后创建字典(以便您将它们作为属性访问),或者显式绑定,或者在将它们存储在字典中之前提取原始函数。

注意,对staticmethod对象的“绑定”仅意味着仅忽略上下文。绑定staticmethod将不变地返回基础函数。

因此,您的选择是使用属性取消缩进字典并触发描述符协议:

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

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

或显式绑定,传入一个虚拟上下文(无论如何将被忽略):

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

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

或直接使用__func__属性访问基础函数:

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

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

但是,如果您要做的只是为一堆函数提供名称空间,则不应首先使用类对象。将功能放在模块中。这样一来,您不必staticmethod首先使用装饰器,也不必再次拆开它们。


15
最后的说明是最重要的部分,IMO。我们可以只创建一个模块中所需的所有功能的列表,然后循环调用它们。
阿西姆(Azim)

3

除了Pieters的答案,您还可以删除@staticmethod

class A(object):
    def open():
        return 123

    def proccess():
        return 456

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

obj = A.switch[1]()

然而,在这种方式,你不能打电话openprocessself。您可以使用A.open()A.process()或仅使用 open()process()而不使用它们A.(当然,仅当您在类中时)才可以调用它们。


有了这种可能,为什么@staticmethod装饰器甚至包含在python中?
Rhdr

1
@Rhdr我想@staticmethod能够访问静态方法有self.self.__dict__并且self.__getattribute__,与普通的动态方法一致。(我没试过__dict__/ __getattribute__,但他们应该工作)(参见实施@staticmethodstackoverflow.com/a/60383279/8535456
青山
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.