Python 在类体内调用类静态方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12718187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:41:19  来源:igfitidea点击:

Calling class staticmethod within the class body?

pythondecoratorstatic-methods

提问by martineau

When I attempt to use a static method from within the body of the class, and define the static method using the built-in staticmethodfunction as a decorator, like this:

当我尝试在类的主体中使用静态方法,并使用内置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

I get the following error:

我收到以下错误:

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

I understand why this is happening (descriptor binding), and can work around it by manually converting _stat_func()into a staticmethod after its last use, like so:

我理解为什么会发生这种情况(描述符绑定),并且可以通过_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

So my question is:

所以我的问题是:

Are there better, as in cleaner or more "Pythonic", ways to accomplish this?

有没有更好的方法,比如更干净或更“Pythonic”的方法来实现这一点?

采纳答案by Ben

staticmethodobjects apparently have a __func__attribute storing the original raw function (makes sense that they had to). So this will work:

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


As an aside, though I suspected that a staticmethod object had some sort of attribute storing the original function, I had no idea of the specifics. In the spirit of teaching someone to fish rather than giving them a fish, this is what I did to investigate and find that out (a C&P from my Python session):

顺便说一句,虽然我怀疑静态方法对象具有某种存储原始函数的属性,但我不知道具体细节。本着教别人钓鱼而不是给他们一条鱼的精神,这就是我所做的调查和发现(来自我的 Python 会话的 C&P):

>>> 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>

Similar sorts of digging in an interactive session (diris very helpful) can often solve these sorts of question very quickly.

在交互式会话中进行类似的挖掘(dir非常有帮助)通常可以非常快速地解决此类问题。

回答by Pedro Romano

What about injecting the class attribute after the class definition?

在类定义之后注入类属性怎么样?

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

回答by Keith

This is due to staticmethod being a descriptor and requires a class-level attribute fetch to exercise the descriptor protocol and get the true callable.

这是因为 staticmethod 是一个描述符并且需要类级别的属性获取来执行描述符协议并获得真正的可调用对象。

From the source code:

从源代码:

It can be called either on the class (e.g. C.f()) or on an instance (e.g. C().f()); the instance is ignored except for its class.

它可以在类(例如C.f())或实例(例如C().f())上调用;除了它的类之外,该实例被忽略。

But not directly from inside the class while it is being defined.

但不是在定义时直接从类内部。

But as one commenter mentioned, this is not really a "Pythonic" design at all. Just use a module level function instead.

但正如一位评论者所提到的,这根本不是真正的“Pythonic”设计。只需使用模块级函数即可。

回答by schatten

What about this solution? It does not rely on knowledge of @staticmethoddecorator implementation. Inner class StaticMethod plays as a container of static initialization functions.

这个解决方案怎么样?它不依赖于@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

回答by Jan Vorcak

This is the way I prefer:

这是我更喜欢的方式:

class Klass(object):

    @staticmethod
    def stat_func():
        return 42

    _ANS = stat_func.__func__()

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

I prefer this solution to Klass.stat_func, because of the DRY principle. Reminds me of the reason why there is a new super()in Python 3 :)

Klass.stat_func由于DRY 原则,我更喜欢这个解决方案。让我想起了 Python 3 中有新内容super()原因:)

But I agree with the others, usually the best choice is to define a module level function.

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

For instance with @staticmethodfunction, the recursion might not look very good (You would need to break DRY principle by calling Klass.stat_funcinside Klass.stat_func). That's because you don't have reference to selfinside static method. With module level function, everything will look OK.

例如,对于@staticmethod函数,递归可能看起来不太好(您需要通过调用Klass.stat_funcinside来打破 DRY 原则Klass.stat_func)。那是因为您没有对self内部静态方法的引用。使用模块级功能,一切都会好起来的。