Python's .__call__() Method: Creating Callable Instances :

Python's .__call__() Method: Creating Callable Instances
by:
blow post content copied from  Real Python
click here to view original post


In Python, a callable is any object that you can call using a pair of parentheses and, optionally, a series of arguments. Functions, classes, and methods are all common examples of callables in Python. Besides these, you can also create custom classes that produce callable instances. To do this, you can add the .__call__() special method to your class.

Instances of a class with a .__call__() method behave like functions, providing a flexible and handy way to add functionality to your objects. Understanding how to create and use callable instances is a valuable skill for you as a Python developer.

In this tutorial, you’ll:

  • Understand the concept of callable objects in Python
  • Create callable instances by providing your classes with a .__call__() method
  • Understand the difference between .__init__() and .__call__()
  • Code several examples of using callable instances to solve real-world problems

To get the most out of this tutorial, you should be comfortable with the basics of object-oriented programming in Python, including how to define and use classes and methods. Some familiarity with Python decorators and the strategy design pattern will also help. You should also understand the concept of state.

Understanding Callable Objects in Python

A callable in Python is any object that you can call using a pair of parentheses and a series of arguments if required. You’ll find different examples of callables in your daily interaction with Python. Some of them include:

All these different callables have something in common. They all implement the .__call__() special method. To confirm this fact, you can use the built-in dir() function, which takes an object as an argument and returns the object’s list of attributes and methods:

>>>
>>> dir(abs)
[
    '__call__',
    '__class__',
    ...
]

>>> dir(all)
[
    '__call__',
    '__class__',
    ...
]

>>> def greet():
...     print("Hello, World!")
...

>>> dir(greet)
[
    '__annotations__',
    '__builtins__',
    '__call__',
    ...
]

In the first two examples, you call dir() with the built-in abs() and all() functions as arguments. In both cases, you can see that the .__call__() method is present in the output.

In the final example, you define a custom function that prints a message to the screen. This function also has .__call__(). Note how you can use this method to call the function:

>>>
>>> greet.__call__()
Hello, World!

Note that using .__call__() as you did in this example produces the same effect as calling the function directly with greet().

Now, how does all this work internally? When you run something like callable_object(*args, **kwargs), Python internally translates the operation into callable_object.__call__(*args, **kwargs). The arguments to the regular function are the same as those used in .__call__(). In other words, whenever you call a callable object, Python automatically runs its .__call__() method behind the scenes using the arguments you’ve passed into the callable.

Now take a look at the following custom class:

>>>
>>> class SampleClass:
...     def method(self):
...         print("You called method()!")
...

>>> type(SampleClass)
<class 'type'>

>>> dir(type)
[
    '__abstractmethods__',
    '__annotations__',
    '__base__',
    '__bases__',
    '__basicsize__',
    '__call__',
    ...
]

>>> sample_instance = SampleClass()
>>> dir(sample_instance.method)
[
    '__call__',
    '__class__',
    ...
]

In Python, everything is an object. Classes like SampleClass are objects of type, which you can confirm by calling type() with the class object as an argument or by accessing the .__class__ attribute.

The class constructor of SampleClass falls back to using type.__call__(). That’s why you can call SampleClass() to get a new instance. So, class constructors are callable objects that return new instances of the underlying class.

In the example above, you can observe that method objects, like sample_instance.method, also have a .__call__() special method that turns them into callable objects. The main takeaway here is that to be callable, an object needs to have a .__call__() method.

If you inspect a closure, generator function, or asynchronous function, then you’ll get similar results. You’ll always find a .__call__() method in callable objects.

Checking Whether an Object Is Callable

If you ever need to check whether a Python object is callable, then you can use the built-in callable() function like in the following examples:

Read the full article at https://realpython.com/python-callable-instances/ »


[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]


May 24, 2023 at 07:30PM
Click here for more details...

=============================
The original post is available in Real Python by
this post has been published as it is through automation. Automation script brings all the top bloggers post under a single umbrella.
The purpose of this blog, Follow the top Salesforce bloggers and collect all blogs in a single place through automation.
============================

Salesforce