且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2022-12-16 20:39:38

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

You are storing unbound staticmethod objects in a dictionary. Such objects (as well as classmethod objects, functions and property objects) are only bound through the descriptor protocol, by accessing the name as an attribute on the class or an instance. Directly accessing the staticmethod objects in the class body is not an attribute access.

要么在创建类之后创建字典(这样你就可以将它们作为属性访问),或者显式绑定,或者在将它们存储到字典之前提取原始函数.

Either create the dictionary after creating the class (so you access them as attributes), or bind explicitly, or extract the original function before storing them in the dictionary.

请注意,staticmethod 对象的绑定"仅意味着上下文被忽略;绑定的 staticmethod 返回底层函数不变.

Note that 'binding' for staticmethod objects merely means that the context is merely ignored; a bound staticmethod returns the underlying function unchanged.

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

So your options are to unindent the dictionary and trigger the descriptor protocol by using attributes:

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

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

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

or to bind explicitly, passing in a dummy context (which will be ignored anyway):

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

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

或者直接使用 __func__ 属性访问底层函数:

or access the underlying function directly with the __func__ attribute:

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

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

然而,如果您所做的只是为一堆函数提供一个命名空间,那么您首先不应该使用类对象.将函数放在模块中.这样一来,您就不必首先使用 staticmethod 装饰器,也不必再次打开它们.

However, if all you are trying to do is provide a namespace for a bunch of functions, then you should not use a class object in the first place. Put the functions in a module. That way you don't have to use staticmethod decorators in the first place and don't have to unwrap them again.