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

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -