使用decorator和staticmethod函数的区别

2024-10-02 00:34:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一个类,该类得到一个函数,然后从该实例运行。然而,当我尝试使用staticmethod时,我发现使用decorator和只传递staticmethod函数之间有区别

class WithDec():
    def __init__(self):
        pass

    @staticmethod
    def stat(val):
        return val + 1


def OuterStat(val):
    return val + 1

class WithoutDec():
    def __init__(self, stat):
        self.stat = staticmethod(stat)

对于这两个类,会发生以下情况

>>> WithDec().stat(2)
3
>>> WithoutDec(OuterStat).stat(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable

发生了什么,我能做些什么来阻止它


Tags: 实例函数selfreturninitdefdecoratorval
3条回答

静态方法仍然通过描述符协议工作,这意味着当它是属性时,通过实例访问它仍然意味着__get__方法将被调用以返回实际被调用的对象。就是

WithDec().stat(2)

相当于

w = WithDec()
w.stat(2)

这相当于

WithDec.stat.__get__(w, WithDec)(2)

但是,当静态方法是一个实例属性时,描述符协议不会被调用,就像WithoutDec的情况一样。那么

WithoutDec().stat(2)

尝试调用文本staticmethod实例stat,而不是stat.__get__返回的函数

您想要的是使用staticmethod创建类属性,而不是通过decorator语法:

class WithoutDec():

    def stat(val):
        return val + 1

    stat = staticmethod(stat)

首先将stat绑定到一个常规函数(在尝试将它作为实例方法使用之前,它实际上不是一个实例方法),然后用一个staticmethod实例包装原始函数替换该函数

问题是您试图在__init__内使用staticmethod(),它用于创建类的实例,而不是直接在类级别上使用staticmethod(),后者定义类、类的方法及其静态方法

此代码适用于:

def OuterStat(val):
    return val + 1

class WithoutDec():
    stat = staticmethod(OuterStat)
>>> WithoutDec.stat(2)
3

请注意,尝试使用自己的、不同的stat版本创建WithoutDec实例与静态方法的含义相反

我在this thread上找到了一个非常鼓舞人心的解决方案。事实上,您的代码不是很pythonic,并且将静态方法属性化为类实例的属性。以下代码起作用:

class WithoutDec():
    
    stat = None

    @staticmethod
    def OuterStat(val):
        return val + 1

然后你打电话:

my_without_dec = WithoutDec()
my_without_dec.stat = WithotuDec.OuterStat
my_without_dec.stat(2)

稍后,如果要创建新方法,请调用:

def new_func(val):
    return val+1

WithoutDec.newStat = staticmethod(new_func)
my_without_dec.stat = WithoutDec.newStat
my_without_dec.stat(2)

相关问题 更多 >

    热门问题