I am learning the concept of classmethods
in python.
class A():
n=0
# object method
def func_o(self):
self.n += 1
print self.n
# well, class method
@classmethod
def func_c(cls):
cls.n += 1
print cls.n
when checking the callable()
attributes of the class, I came across with this peculiar output:
>>> [(k, callable(v)) for k,v in A.__dict__.items()]
[('__module__', False), ('__doc__', False), ('func_o', True), ('func_c', False), ('n', False)]
('func_o', True)
even though the class __dict__
was inspected, similarly ('func_c', False)
for some reason.
Can someone explain?
But in Python, this would lead to the Typeerror: int object is not callable error. To fix this error, you need to let Python know you want to multiply the number outside the parentheses with the sum of the numbers inside the parentheses. Python allows you to specify any arithmetic sign before the opening parenthesis.
The classmethod() is an inbuilt function in Python, which returns a class method for a given function.; Syntax: classmethod(function) Parameter :This function accepts the function name as a parameter. Return Type:This function returns the converted class method.
A classmethod
object is not a function object, no. It is not meant to be callable.
classmethod
objects are descriptors; descriptors facilitate the binding of an object to a specific instance or class. Functions and properties are also descriptors; binding produces methods, or the property value, respectively. See the Python Descriptor How To. If you were to access a classmethod
descriptor on the class, then this triggers a classmethod.__get__(None, cls)
call that produces a bound method (which, when called, invokes the original function with the class object passed in as the first argument).
When you access all class attributes through the __dict__
attribute, you are bypassing the descriptor protocol, so you get the raw descriptor objects themselves.
Either access the object on the class (and thus trigger the descriptor.__get__(None, cls)
call that binds class methods to the class object), manually bind, or test explicitly for classmethod
objects:
>>> A.__dict__['func_c']
<classmethod object at 0x1018e6cc8>
>>> A.__dict__['func_c'].__get__(None, A) # explicitly bind to a class
<bound method classobj.func_c of <class __main__.A at 0x101c52328>>
>>> callable(A.__dict__['func_c'].__get__(None, A))
True
>>> A.func_c # trigger the protocol and bind to a class
<bound method classobj.func_c of <class __main__.A at 0x101c52328>>
You can also access the original function that the classmethod
object wraps, using the __func__
attribute:
>>> A.__dict__['func_c'].__func__
<function func_c at 0x101c59668>
which is, of course, itself callable too.
Note that this all applies to staticmethod
objects too; a staticmethod
object, when bound, just returns the original 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