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'>
I provide below a more detailed example:
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()
> python2.7 test.py
Is bar() callable? True
Is foo() callable? True
bar True <type 'function'>
foo False <type 'staticmethod'>
> python3.4 test.py
Is bar() callable? True
Is foo() callable? True
bar True <class 'function'>
foo False <class 'staticmethod'>
What is a static method? Static methods in Python are extremely similar to python class level methods, the difference being that a static method is bound to a class rather than the objects for that class. This means that a static method can be called without an object for that class.
Class method can access and modify the class state. Static Method cannot access or modify the class state. The class method takes the class as parameter to know about the state of that class. Static methods do not know about class state.
A static method can be called from either a class or object reference. We can call it Utils if foo() is a static function in Class Utils. Utils. foo() as well as Utils().
Static methods have a limited use case because, like class methods or any other methods within a class, they cannot access the properties of the class itself. However, when you need a utility function that doesn't access any properties of a class but makes sense that it belongs to the class, we use static functions.
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'>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With