使用 __dict__,我的@staticmethod 不是 callable.
Python 2.7.5(默认,2016 年 8 月 29 日,10:12:21)[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] 在 linux2输入帮助"、版权"、信用"或许可"以获取更多信息.>>>从 __future__ 导入(absolute_import、除法、print_function)>>>C类(对象):... @staticmethod...定义 foo():...对于名称,C.__dict__.items() 中的 val:...如果名称[:2] != '__':...打印(名称,可调用(val),类型(val))...>>>C.foo()foo False- 这怎么可能?
- 如何检查静态方法是否可调用?
我在下面提供了一个更详细的例子:
脚本 test.pyfrom __future__ import (absolute_import, Division, print_function)C类(对象):@静态方法定义 foo():返回 42定义栏(自我):print('bar() 是否可以调用?', callable(C.bar))打印('foo()是否可调用?',可调用(C.foo))对于属性,C.__dict__.items() 中的值:如果属性 [:2] != '__':打印(属性,'\t',可调用(值),'\t',类型(值))c = C()c.bar()python2 的结果
>python2.7 test.pybar() 可以调用吗?真的foo() 是可调用的吗?真的bar True <type 'function'>foo Falsepython3 的结果相同
>python3.4 test.pybar() 可以调用吗?真的foo() 是可调用的吗?真的bar True foo False 解决方案这种行为的原因是描述符协议.C.foo 不会返回 staticmethod 而是一个普通函数,而 __dict__ 中的 'foo' 是一个 staticmethod(和 staticmethod 是一个描述符).
简而言之 C.foo 在这种情况下与 C.__dict__['foo'] 不同 - 而是 C.__dict__['foo'].__get__(C)(另请参阅 描述符上的数据模型):
>>>callable(C.__dict__['foo'].__get__(C))真的>>>类型(C.__dict__['foo'].__get__(C))功能>>>可调用(C.foo)真的>>>类型(C.foo)功能>>>C.foo 是 C.__dict__['foo'].__get__(C)真的在您的情况下,我会使用 getattr 检查可调用对象(知道描述符以及如何访问它们)而不是存储在 __dict__ 类中的值:
def bar(self):print('bar() 是否可以调用?', callable(C.bar))打印('foo()是否可调用?',可调用(C.foo))对于 C.__dict__.keys() 中的属性:如果属性 [:2] != '__':value = getattr(C, 属性)打印(属性,'\t',可调用(值),'\t',类型(值))打印(在 python-3.x 上):
bar() 是否可以调用?真的foo() 是可调用的吗?真的bar True foo Truepython-2.x 的类型不同,但是 callable 的结果是一样的:
bar() 是否可以调用?真的foo() 是可调用的吗?真的bar True <type 'instancemethod'>foo True <type 'function'>While parsing attributes using __dict__, my @staticmethod is not 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'>
- How is this possible?
- How to check if a static method is callable?
I provide below a more detailed example:
Script 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()Result for python2
> python2.7 test.py Is bar() callable? True Is foo() callable? True bar True <type 'function'> foo False <type 'staticmethod'>Same result for python3
> python3.4 test.py Is bar() callable? True Is foo() callable? True bar True <class 'function'> foo False <class 'staticmethod'>解决方案
The reason for this behavior is the descriptor protocol. The C.foo won't return a staticmethod but a normal function while the 'foo' in __dict__ is a staticmethod (and staticmethod is a descriptor).
In short C.foo isn't the same as C.__dict__['foo'] in this case - but rather C.__dict__['foo'].__get__(C) (see also the section in the documentation of the Data model on descriptors):
>>> 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
In your case I would check for callables using getattr (which knows about descriptors and how to access them) instead of what is stored as value in the class __dict__:
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))Which prints (on python-3.x):
Is bar() callable? True Is foo() callable? True bar True <class 'function'> foo True <class 'function'>The types are different on python-2.x but the result of callable is the same:
Is bar() callable? True Is foo() callable? True bar True <type 'instancemethod'> foo True <type 'function'>
更多推荐
Python 静态方法并不总是可调用的
发布评论