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