I am trying to understand what 'callables' are in Python and what it means for a class to be callable. I was playing with the following code:
class A(object):
def __init__(self):
pass
print("Is A callable? " + str(callable(A)))
a=A()
print("created a")
a()
This gives the following result:
Is A callable? True
created a
Traceback (most recent call last):
File "test2.py", line 11, in <module>
a()
TypeError: 'A' object is not callable
Furthermore,
print(type(A.__call__()))
Gives:
<class '__main__.A'>
Does this mean that class A has a __call__
method? and why is it of type class?
is A.__call__()
being called each time I instantiate with A()?
callable() is a built-in method in Python that checks if a passed object appears to be callable. To do this, it checks if the argument is either of the following: The type that demonstrates callability, such as a function or a method. An instance of a class with a __call__ method.
Definition of callable : capable of being called specifically : subject to a demand for presentation for payment callable bond.
A callable object, in computer programming, is any object that can be called like a function.
So, start with the fact that in Python, ordinarily functions are callable, and classes are callable.
Leaving apart the mechanisms that mark functions as callable, Python classes have, as you know, special methods. The method that makes instances of a class callable is __call__
. So, if your class has an explicit __call__
method, its instances are callable and end of story: when you call the instance, it is the __call__
method that is called.
That answers half your question - now let's check what the __call__
method on the class of classes does.
Classes in Python are themselves also first class objects - but they have to be an instance of type
. That is, calling type
as one calls a class to create an instance, creates a new class
. The Python runtime does this automatically when a class body block is met in code.
(but one can also create new classes programmaticaly by explicitly calling type
in its three+ parameter form)
As type
itself is a subclass of object
- its __new__
method is what it has of special, as it creates a new class, filling up all needed data structures as required by the cPython ABI, allocating memory, and putting values into fields that are not accessible from pure Python codes. As it is the class for any kind of class-object in Python it is called a metaclas. One can derive other classes from type
and create custom metaclasses, to run code,r insert attributes, register data and so on at the moment classes are created - but that is optional. Any class created goes through type
's __new__
.
And when you instantiate a class? I wrote above that what makes an object callable in Python is the presence of a __call__
method in its class. type
being the class of all classes, it does feature a __call__
method - and it contains the code needed to orchestrate the call to the class' __new__
and __init__
methods. And that is why classes are callable, and why Python can use the same syntax for function calls and object instantiation.
is
A.__call__()
being called each time I instantiate with A()?
Not properly - what is called is type(A).__call__
. A.__call__
and type(A).__call__
will be the same if there is no explict __call__
method defined in A
(then its class, type
is searched for __call__
. But special methods are not called implicitly by Python by ordinary attribute retrieval: they are always picked from the object's class - and that is made inside the runtime.
You might be confused for the metaclass' call not to be available to the class: that is simply not defined like that in the method retrieval algorithms from Python. When you ask for an attribute or method of an object- including a special method like __call__
, the class is searched for the attribute in the form a descriptor (to provide custom attribute access) - and then the base classes of that class, but not the class of that class. (Also, for special methods, they are only special if they are defined in the object's class itself: being attached directly to an instance have no effect).
The key document where this is all published is the Python's Data Model - it can take some time and experimenting to figure everything out from there, though.
When a __something__
method of an object is called, something like this happens:
Note that it never looks at the object's class's class.
Since classes are instances of type
(or a subclass of it, see here), classes are callable (type
has __call__
). However, unless the class also defines __call__
, its instances won't have it, because it will never look in the class's class.
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