【问题标题】:'staticmethod' object is not callable“staticmethod”对象不可调用
【发布时间】:2017-06-14 17:53:28
【问题描述】:

我有这个代码:

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

如何解决?

【问题讨论】:

标签: python


【解决方案1】:

您将未绑定 staticmethod 对象存储在字典中。此类对象(以及classmethod 对象、函数和property 对象)仅通过descriptor protocol 绑定,方法是将名称作为类或实例的属性访问。直接访问类体中的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 装饰器,也不必再次打开它们。

【讨论】:

  • 最后的注释是最重要的部分,IMO。我们可以从一个模块中创建一个我们想要的所有函数的列表,然后循环调用它们。
【解决方案2】:

除了 Pieters 的回答,你可以直接删除@staticmethod

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

    def proccess():
        return 456

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

obj = A.switch[1]()

但是,通过这种方式,就无法使用self 调用openprocess

  • 在类之外可以使用A.open()A.process() 调用它们,就像常见的静态方法一样。
  • 在类中,可以只使用open()process() 调用它们,而无需A.。然而,
    • A.open 将失败。 (我只用装饰器测试了这个案例。(@open))
    • 此外,它们必须放在调用它们的函数之前。

【讨论】:

  • 既然有可能,为什么 @staticmethod 装饰器甚至包含在 python 中?
  • @Rhdr 我认为@staticmethod 可以使用self.self.__dict__self.__getattribute__ 访问静态方法,与常见的动态方法一致。 (我还没有尝试过__dict__/__getattribute__,但它们应该可以工作)(参见@staticmethodstackoverflow.com/a/60383279/8535456的实现)
猜你喜欢
  • 2021-09-29
  • 2019-08-14
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2018-09-30
  • 2021-02-18
  • 1970-01-01
  • 2016-10-01
相关资源
最近更新 更多