The reason for this behavior is the descriptor protocol. C.foo does not return a staticmethod , but a normal function, and the 'foo' in __dict__ is a staticmethod (and staticmethod is a handle).
In short, C.foo in this case does not match C.__dict__['foo'] , but rather C.__dict__['foo'].__get__(C) (see also the section in the Data Model for Descriptors documentation):
>>> 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 the use of called objects using getattr (which knows about descriptors and how to access them) instead of what is stored as a value in the __dict__ class:
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))
What prints (in python-3.x):
Is bar() callable? True Is foo() callable? True bar True <class 'function'> foo True <class 'function'>
The types of python-2.x are different, but the callable result callable same:
Is bar() callable? True Is foo() callable? True bar True <type 'instancemethod'> foo True <type 'function'>
MSeifert Jul 28 '17 at 14:30 2017-07-28 14:30
source share