Python static method is not always callable -
while parsing attributes using __dict__, @staticmethod 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" more information. >>> __future__ import (absolute_import, division, print_function) >>> class c(object): ... @staticmethod ... def foo(): ... name, val in c.__dict__.items(): ... if name[:2] != '__': ... print(name, callable(val), type(val)) ... >>> c.foo() foo false <type 'staticmethod'> - how possible?
- how check if static method callable?
i provide below 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)) attribute, value in c.__dict__.items(): if attribute[:2] != '__': print(attribute, '\t', callable(value), '\t', type(value)) c = c() c.bar() result python2
> python2.7 test.py bar() callable? true foo() callable? true bar true <type 'function'> foo false <type 'staticmethod'> same result python3
> python3.4 test.py bar() callable? true foo() callable? true bar true <class 'function'> foo false <class 'staticmethod'>
the reason behavior descriptor protocol. c.foo won't return staticmethod normal function while 'foo' in __dict__ staticmethod (and staticmethod descriptor).
in short c.foo isn't same c.__dict__['foo'] in case - rather c.__dict__['foo'].__get__(c) (see section in documentation of 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 c.__dict__['foo'].__get__(c) true in case check callables using getattr (which knows descriptors , how access them) instead of stored value in class __dict__:
def bar(self): print('is bar() callable?', callable(c.bar)) print('is foo() callable?', callable(c.foo)) 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 foo() callable? true bar true <class 'function'> foo true <class 'function'> the types different on python-2.x result of callable same:
is bar() callable? true foo() callable? true bar true <type 'instancemethod'> foo true <type 'function'>
Comments
Post a Comment