调用类的类体中STATICMETHOD?(Calling class staticmethod wi

2019-06-18 10:22发布

当我尝试使用内置的使用静态方法从类的体内,并定义静态方法staticmethod的功能作为装饰,就像这样:

class Klass(object):

    @staticmethod  # use as decorator
    def _stat_func():
        return 42

    _ANS = _stat_func()  # call the staticmethod

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

我得到以下错误:

Traceback (most recent call last):<br>
  File "call_staticmethod.py", line 1, in <module>
    class Klass(object): 
  File "call_staticmethod.py", line 7, in Klass
    _ANS = _stat_func() 
  TypeError: 'staticmethod' object is not callable

我明白为什么会发生(描述符的结合),并且可以通过手动转换解决它_stat_func()到一个静态方法在最后一次使用后,就像这样:

class Klass(object):

    def _stat_func():
        return 42

    _ANS = _stat_func()  # use the non-staticmethod version

    _stat_func = staticmethod(_stat_func)  # convert function to a static method

    def method(self):
        ret = Klass._stat_func() + Klass._ANS
        return ret

所以我的问题是:

有没有更好的,如清洁剂或更多的“Python化”的方式来做到这一点?

Answer 1:

staticmethod的对象显然有__func__属性保管原生功能(是有道理的,他们不得不)。 因此,这将工作:

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    _ANS = stat_func.__func__()  # call the staticmethod

    def method(self):
        ret = Klass.stat_func()
        return ret

顺便说一句,虽然我怀疑是一个静态方法对象有某种属性保管原有功能的,我没有具体的想法。 在教人以渔,而不是给他们一条鱼的精神,这是我做的调查,发现了(一个C&P从我的Python会话):

>>> class Foo(object):
...     @staticmethod
...     def foo():
...         return 3
...     global z
...     z = foo

>>> z
<staticmethod object at 0x0000000002E40558>
>>> Foo.foo
<function foo at 0x0000000002E3CBA8>
>>> dir(z)
['__class__', '__delattr__', '__doc__', '__format__', '__func__', '__get__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> z.__func__
<function foo at 0x0000000002E3CBA8>

类似种种在交互式会话挖掘( dir是非常有帮助的)往往可以解决这些问题的种类非常快。



Answer 2:

这是我喜欢的方式:

class Klass(object):

    @staticmethod
    def stat_func():
        return 42

    _ANS = stat_func.__func__()

    def method(self):
        return self.__class__.stat_func() + self.__class__._ANS

我喜欢这个解决方案Klass.stat_func因为, DRY原则 。 让我想起了为什么有一个新的理由super()在Python 3 :)

但我同意其他人,通常是最好的选择是定义一个模块级的功能。

例如与@staticmethod功能,递归可能不是很好看(你可能需要通过调用打破DRY原则Klass.stat_funcKlass.stat_func )。 那是因为你没有提到self的静态方法里面。 随着模块级的功能,一切看起来OK。



Answer 3:

这是由于静态方法是一个描述符,需要一个类级属性取行使描述协议,并得到真正的调用。

从源代码:

它可以被称为无论是在类别(例如Cf()或上的一个实例(例如, C().f() ); 除了它的类实例被忽略。

但是,从里面的类不能直接当它被定义。

但是如前所述一个评论,这是不是真的在所有一个“Python化”设计。 只需使用一个模块级函数。



Answer 4:

怎么样的类定义后注射类的属性?

class Klass(object):

    @staticmethod  # use as decorator
    def stat_func():
        return 42

    def method(self):
        ret = Klass.stat_func()
        return ret

Klass._ANS = Klass.stat_func()  # inject the class attribute with static method value


Answer 5:

这个怎么样的解决方案? 它不依赖于知识@staticmethod装饰的实现。 内部类STATICMETHOD扮演的静态初始化函数的容器。

class Klass(object):

    class StaticMethod:
        @staticmethod  # use as decorator
        def _stat_func():
            return 42

    _ANS = StaticMethod._stat_func()  # call the staticmethod

    def method(self):
        ret = self.StaticMethod._stat_func() + Klass._ANS
        return ret


Answer 6:

根据下面的博客,调用类中的一个静态方法时,调用函数必须是一个类的方法,因此增加@classmethod你的方法定义可以解决这个问题。

关于如何使用静态,类或抽象方法在Python的权威指南



文章来源: Calling class staticmethod within the class body?