Calling class staticmethod within the class body?
当我试图从类的主体中使用静态方法,并使用内置的
1 2 3 4 5 6 7 8 9 10 11 | 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 |
我得到以下错误:
1 2 3 4 5 6 | Traceback (most recent call last): 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 |
我理解发生这种情况的原因(描述符绑定),并且可以在上次使用后通过手动将
1 2 3 4 5 6 7 8 9 10 11 12 | 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"来实现这一点?
1 2 3 4 5 6 7 8 9 10 11 | 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 |
顺便提一句,尽管我怀疑StaticMethod对象具有某种存储原始函数的属性,但我不知道具体细节。本着教别人钓鱼而不是给他们一条鱼的精神,我这样做是为了调查并发现这一点(我的Python课程中的C&P):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | >>> 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> |
在交互式会话中进行类似的挖掘(
我喜欢这样:
1 2 3 4 5 6 7 8 9 10 | class Klass(object): @staticmethod def stat_func(): return 42 _ANS = stat_func.__func__() def method(self): return self.__class__.stat_func() + self.__class__._ANS |
由于干燥原理,我更喜欢这个解决方案。提醒我为什么在python 3中有一个新的
但我同意其他人的观点,通常最好的选择是定义一个模块级的函数。
例如,对于
这是由于StaticMethod是一个描述符,需要一个类级属性获取来执行描述符协议并获得真正的可调用性。
从源代码:
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.
但不能直接从类内部定义。
但正如一位评论家所说,这根本不是一个"Python"设计。只需使用模块级函数。
这个解决方案怎么样?它不依赖于
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
在类定义之后注入类属性怎么样?
1 2 3 4 5 6 7 8 9 10 11 | 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 |
根据下面的博客,在类内调用静态方法时,调用函数必须是类方法,因此在方法定义中添加
关于如何在Python中使用静态、类或抽象方法的最终指南