在使用__dict__
解析属性时,我的@staticmethod
不是callable
。
Python 2.7.5 (default, Aug 29 2016, 10:12:21)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import (absolute_import, division, print_function)
>>> class C(object):
... @staticmethod
... def foo():
... for name, val in C.__dict__.items():
... if name[:2] != '__':
... print(name, callable(val), type(val))
...
>>> C.foo()
foo False <type 'staticmethod'>
我在下面提供了一个更详细的例子:
test.py
from __future__ import (absolute_import, division, print_function)
class C(object):
@staticmethod
def foo():
return 42
def bar(self):
print('Is bar() callable?', callable(C.bar))
print('Is foo() callable?', callable(C.foo))
for attribute, value in C.__dict__.items():
if attribute[:2] != '__':
print(attribute, '\t', callable(value), '\t', type(value))
c = C()
c.bar()
> python2.7 test.py
Is bar() callable? True
Is foo() callable? True
bar True <type 'function'>
foo False <type 'staticmethod'>
> python3.4 test.py
Is bar() callable? True
Is foo() callable? True
bar True <class 'function'>
foo False <class 'staticmethod'>
答案 0 :(得分:9)
此行为的原因是描述符协议。如果C.foo
中的staticmethod
为staticmethod
,'foo'
将不会返回__dict__
,而是正常函数(而staticmethod
是描述符)。
在这种情况下,简而言之C.foo
与C.__dict__['foo']
不同 - 而是C.__dict__['foo'].__get__(C)
(另请参阅Data model on descriptors文档中的部分):< / p>
>>> callable(C.__dict__['foo'].__get__(C))
True
>>> type(C.__dict__['foo'].__get__(C))
function
>>> callable(C.foo)
True
>>> type(C.foo)
function
>>> C.foo is C.__dict__['foo'].__get__(C)
True
在你的情况下,我会使用getattr
(它知道描述符及如何访问它们)而不是在类__dict__
中存储为值的内容来检查callables:
def bar(self):
print('Is bar() callable?', callable(C.bar))
print('Is foo() callable?', callable(C.foo))
for attribute in C.__dict__.keys():
if attribute[:2] != '__':
value = getattr(C, attribute)
print(attribute, '\t', callable(value), '\t', type(value))
哪些打印(在python-3.x上):
Is bar() callable? True
Is foo() callable? True
bar True <class 'function'>
foo True <class 'function'>
python-2.x上的类型不同,但callable
的结果是相同的:
Is bar() callable? True
Is foo() callable? True
bar True <type 'instancemethod'>
foo True <type 'function'>
答案 1 :(得分:3)
您无法检查staticmethod
对象是否可以调用。这是在Issue 20309 -- Not all method descriptors are callable中的跟踪器上进行了讨论,并且关闭为#34;而不是错误&#34;。
简而言之,对于staticmethod对象实现__call__
没有理由。内置的callable
无法知道staticmethod
对象本质上是&#34;持有&#34;一个可赎回的。
虽然你可以实现它(对于staticmethod
和classmethod
s),但如前所述,这将是一个维护负担,没有真正的激励用例。
对于您的情况,您可以使用getattr(C, name)
执行名为name
的对象的查找;这相当于执行C.<name>
。 getattr
,在找到staticmethod对象后,将调用其__get__
来取回它管理的可调用对象。然后,您可以使用callable
。
可以在文档中找到关于描述符的精彩入门,请查看Descriptor HOWTO。