Callables in Python


A callable is an object in Python that can be called / executed when called with parantheses ( ). Classes and functions are callable.

Callables can be a class, a function, or an instance of a class. In simple terms, a class/function/instance/builtin is callable if it gets executed while being called with the parantheses ().

Example 1:

In [1]: help()
Welcome to Python 3.6's help utility!
-- content omitted --
In [2]: int()
Out[2]: 0

In [3]: callable(int)
Out[3]: True

In [4]: callable(help)
Out[4]: True

In [5]: def hello():
        ..: print("Howdy!!")

In [6]: hello()

In [7]: callable(hello)
Out[7]: True

In Example 1, we can see that the builtins like help(), a pre-defined type such as int(), and a custom function hello() are all callable. These can be executed while being called with parantheses.

The __call__() method

The callable() builtin helps to determine if an object is callable or not. Internally, it translates to the magic method __call__().

In short:

my_object(*args) translates to my_object.__call__(*args)

All classes and functions are callable, as well as instances of classes with the __call__ magic method. An instance of a class/function is usually not callable (even though the class/function itself is), unless the class carries a __call__ magic method.

In other words, an instance is callable only if the class it is instantiated from contains the __call__ magic method.

  • The inbuilt documentation on callable states:
In [1]: print(callable.__doc__)
Return whether the object is callable (i.e., some kind of function).

Note that classes are callable, as are instances of classes with a
__call__() method.

Example 2:

In [5]: def hello():
       ...: print("Howdy!!")

In [6]: hello()

In [7]: hello.__call__()

In [8]: callable(hello)
Out[8]: True

Example 2 shows that a function when called with the parantheses (including any required arguments) is equivalent to calling the __call__() magic method. ie.. calling a function/class with parantheses translates to calling the __call__() magic method.

Read more on Magic methods in Python

Example 3: Non-callable Instances

In [1]: type(1)
Out[1]: int

In [2]: callable(1)
Out[2]: False

In [3]: x = 1

In [4]: type(x)
Out[4]: int

In [5]: callable(int)
Out[5]: True

In [6]: callable(x)
Out[6]: False

Example 3 above shows that even though the int class is callable, the instances created from the int class are not.

Remember that instances will only be callable if the class from which it was instantiated contains a __call__ method. Inspecting the methods of class int reveals that it does not have a __call__ method.

NOTE: You can view the methods of the int class using help(int) or dir(int).

Example 4: Another example with Classes

In [52]: class tell:
        ...: def __call__(self):
            ...: pass

In [53]: telling = tell()

In [54]: callable(tell)
Out[54]: True

In [55]: callable(telling)
Out[55]: True


In [56]: class test:
        ...: pass

In [57]: testing = test()

In [58]: callable(test)
Out[58]: True

In [59]: callable(testing)
Out[59]: False

Since all classes are by default callable, both the classes tell and test in Example 4 are callable. But the instances of these classes necessarily need not be so. Since the class tell has the magic method __call__, the instance telling is callable. But the instance testing instantiated from the class test is not since the class does not have the magic method. Another set of examples.

Example 5: Non-callable instance of a class

In [1]: class new:
       ...: def foo(self):
           ...: print("Hello")

In [2]: n = new()

In [3]: n()
TypeError Traceback (most recent call last)
 in module()
----> 1 n()

TypeError: 'new' object is not callable

Example 6: Callable instance of the same class

In [4]: class new:
...: def __call__(self):
    ...: print("I'm callable!")

In [5]: n = new()

In [6]: n
Out[6]: at 0x7f7a614b1f98

In [7]: n()
I'm callable!

Example 5  and Example 6 shows how a class is itself callable, but unless it carries a __call__() method, the instances spawned out of it are not so.




Python, Objects, and some more..

Everything in Python is an object, what does that mean? This post tries to discuss some very basic concepts.

What does the following assignment do?

a = 1

Of course, anyone dabbled in code knows this. The statement above creates a container `a` and stores the value `1` in it.

But it seem that’s not exactly what’s happening, at least from Python’s view-point.

When a = 1 is entered or executed by the python interpreter, the following happens in the backend, seemingly unknown to the user.

  • The Python interpreter evaluates the literal 1 and tries to understand what data type can be assigned for it.
    • There are several in-built data types such as str, float, bool, list, dict, set etc..
    • Builtin types are classes implemented in the python core.
    • For a full list of types and explanation, read the python help at python-> help()-> topics -> TYPES
    • Read the help sections for builtin types, eg.. help(int), help(list) etc..
  • The interpreter finds the appropriate builtin type for the literal. Since the literal 1 fits the type int, the interpreter creates an instance from class int() in memory.
    • This instance is called an object since it’s just a blob with some metadata.
    • This object has a memory address, a value, a name in one or more namespace, some metadata etc..
    • type(a) helps in understanding the instance type.
    • In short, an assignment statement simply creates an instance in memory from a pre-defined class.
  • The interpreter reads the LHS (Left hand side) of the statement a = 1, and creates the name a in the current namespace.
    • The name in the namespace is a reference to the object in memory.
    • Through this reference, we can access the data portion as well as the attributes of that object.
    • A single object can have multiple names (references).
  • The name a created in the current namespace is linked to the corresponding object in memory.

When a name that’s already defined is entered at the python prompt, the interpreter reads the namespace, finds the name (reference), goes to the memory location it’s referring to, and pull the value of the object, and prints it on-screen.

Every object has the following features:

  • A single value, available in its data section.
In [1]: a = 1

In [2]: a
Out[2]: 1
  • A single type, since the object is an instance of a pre-defined type class such as int , float etc..
In [3]: type(a)
Out[3]: int
  • Attributes either inherited from the parent type class or defined by the user.
In [10]: dir(a)
...[content omitted]
  • One or more base classes. All new-stlye classes in Python ultimately inherits from the object class.
In [4]: type(a)
Out[4]: int

In [5]: int.mro()
Out[5]: [int, object]

NOTE: a is an instance of the int class, and int inturn inherits from the object class. Read more on Method Resolution Order.

  • A unique ID representing the object.
In [6]: id(a)
Out[6]: 140090033476640
  • Zero, One, or more names.
    • Use dir() to check the current namespace.
    • Use dir(<object-name>) to refer the indirect namespace.

Several other builtins are available in the default namespace without defining them specifically, possible due to the inclusion of the builtin module available under the reference __builtin__ in the current namespace.

For a full list of the pre-defined variables, refer dir(__builtins__)help(__builtin__) or help(builtins) after an import builtins.

A few questions and observations:

Q1. How can an assignment have zero names in the namespace?

Ans: An assignment such as a = 1 creates an object in memory and creates a corresponding name (a in our case) in the namespace. a acts as a reference to the object in memory.

But, simply entering 1 at the python prompt creates an object in memory which is an instance of a type class, without creating the reference in the namespace.

Objects which don’t have a reference from the current namespace are usually garbage-collected due to lack of references. Hence, an object which doesn’t have a reference (a name), or had multiple references (more than one names) but had them deleted (for example, del() gets garbage-collected by python.

If the assignment 1 happens to be at a python prompt, it echoes the literal back after creating the object and reference since the prompt is essentially a REPL (Read Eval Print loop)

Q2. Can an object have more than one name references?

Ans: It’s perfectly fine to have more than one reference to a single object. The example below should explain things very well.

In [1]: a = 5000

In [2]: id(a)
Out[2]: 140441367080400

In [3]: b = a

In [4]: b
Out[4]: 5000

In [5]: id(b)
Out[5]: 140441367080400

In [6]: c = 5000

In [7]: id(c)
Out[7]: 140441367080432

In [8]: a is b
Out[8]: True

In [9]: a == b
Out[9]: True

In [10]: a is c
Out[10]: False

In [11]: a == c
Out[11]: True

The example shown above creates an object with value 5000 and assign it a name a in the current namespace. We checked the identifier of the object using id(a) and found out it to be 140441367080400.

As the next step, we created another name in the namespace, ie.. b which takes in whatever a points to. Hence, b would default to 5000 and it will have the same identifier as a.

This shows that an object in memory can have multiple references in a namespace.

Another object of value 5000 is created with a name c , but we can see that the identifier differs from what id(a) and id(b) is. This shows that c points to an entirely different object in memory.

To test if a is exactly the same object as b, use the keyword is. Meanwhile, if you want to test if two objects contain the same value, use the equality == symbol.