Python 静态方法并不总是可调用的 [英] Python static method is not always callable
问题描述
使用 __dict__
解析属性时a>,我的@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.py
from __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 False
python3 的结果相同
>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)
(另请参阅 描述符上的数据模型):
<小时>
在您的情况下,我会使用 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 True
python-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 静态方法并不总是可调用的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!