Python __call__ special method practical example
Asked Answered
E

16

178

I know that __call__ method in a class is triggered when the instance of a class is called. However, I have no idea when I can use this special method, because one can simply create a new method and perform the same operation done in __call__ method and instead of calling the instance, you can call the method.

I would really appreciate it if someone gives me a practical usage of this special method.

Enclosure answered 28/4, 2011 at 20:54 Comment(3)
related: https://mcmap.net/q/55129/-what-is-a-quot-callable-quot/…Polk
the functionality of _call_ is just like the overloaded operator of () in C++. If you simply create a new method outside of the class, you may not access the internal data in a class.Antibes
The most common use of __call__ is hidden in plain view; it's how you instantiate a class: x = Foo() is really x = type(Foo).__call__(Foo), where __call__ is defined by the metaclass of Foo.Omeara
J
92

Django forms module uses __call__ method nicely to implement a consistent API for form validation. You can write your own validator for a form in Django as a function.

def custom_validator(value):
    #your validation logic

Django has some default built-in validators such as email validators, url validators etc., which broadly fall under the umbrella of RegEx validators. To implement these cleanly, Django resorts to callable classes (instead of functions). It implements default Regex Validation logic in a RegexValidator and then extends these classes for other validations.

class RegexValidator(object):
    def __call__(self, value):
        # validation logic

class URLValidator(RegexValidator):
    def __call__(self, value):
        super(URLValidator, self).__call__(value)
        #additional logic

class EmailValidator(RegexValidator):
    # some logic

Now both your custom function and built-in EmailValidator can be called with the same syntax.

for v in [custom_validator, EmailValidator()]:
    v(value) # <-----

As you can see, this implementation in Django is similar to what others have explained in their answers below. Can this be implemented in any other way? You could, but IMHO it will not be as readable or as easily extensible for a big framework like Django.

Justinjustina answered 28/4, 2011 at 23:33 Comment(3)
So if used correctly, it can make the code more readable. I assume if it is used on the wrong place, it would make the code very unreadable as well.Enclosure
This is an example of how it can be used, but not a good one in my opinion. There's no advantage in this case to having a callable instance. It would be better to have an interface/abstract class with a method, like .validate(); it's the same thing only more explicit. The real value of __call__ is being able to use an instance in a place where a callable is expected. I use __call__ most often when creating decorators, for example.Listed
@Listed Your last two sentences would make for a pretty nice answer to OP's question. Thanks!Erlking
N
136

This example uses memoization, basically storing values in a table (dictionary in this case) so you can look them up later instead of recalculating them.

Here we use a simple class with a __call__ method to calculate factorials (through a callable object) instead of a factorial function that contains a static variable (as that's not possible in Python).

class Factorial:
    def __init__(self):
        self.cache = {}
    def __call__(self, n):
        if n not in self.cache:
            if n == 0:
                self.cache[n] = 1
            else:
                self.cache[n] = n * self.__call__(n-1)
        return self.cache[n]

fact = Factorial()

Now you have a fact object which is callable, just like every other function. For example

for i in xrange(10):                                                             
    print("{}! = {}".format(i, fact(i)))

# output
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880

And it is also stateful.

Needle answered 28/4, 2011 at 20:56 Comment(9)
I'd rather have a fact object that is indexable since your __call__ function is essentially an index. Also would use a list instead of a dict, but that's just me.Julie
This can be done with closures as well (and that wouldn't be one of the cases of "oh, X and Y are theoretically equivalent, let's go out of our way to emulate one with the other when it doesn't make the slightest sense" scenarios, the code would be even shorter and, arguably, more readable).Smalt
@delnan - Almost anything can be done several distinct ways. Which one's more readable depends on the reader.Julie
@Chris Lutz: You're free to contemplate those kinds of changes. For memoization in general, a dictionary works out well because you can't guarantee the order in which things fill up your list. In this case, a list might work, but it's not going to be any faster or simpler.Needle
@delnan: This is not intended to be shortest. No one wins at code golf. It's intended to show __call__, be simple and nothing more.Needle
But it kind of ruins the example when the demonstrated technique isn't ideal for the tasks, doesn't it? (And I wasn't about the "let's save lines for the heck of it"-short, I was talking about the "write it in this equally clear manner and save some boilerplate code"-short. Rest assured that I'm not one of those madmen trying to write the shortest code possible, I merely want to avoid boilerplate code that adds nothing for the reader.)Smalt
@delnan: Please include code in your answer to make your point clearer.Needle
That is a helpful explanation.Chem
@S.Lott, this helped me understand this concept! Thanks! +1Decima
J
92

Django forms module uses __call__ method nicely to implement a consistent API for form validation. You can write your own validator for a form in Django as a function.

def custom_validator(value):
    #your validation logic

Django has some default built-in validators such as email validators, url validators etc., which broadly fall under the umbrella of RegEx validators. To implement these cleanly, Django resorts to callable classes (instead of functions). It implements default Regex Validation logic in a RegexValidator and then extends these classes for other validations.

class RegexValidator(object):
    def __call__(self, value):
        # validation logic

class URLValidator(RegexValidator):
    def __call__(self, value):
        super(URLValidator, self).__call__(value)
        #additional logic

class EmailValidator(RegexValidator):
    # some logic

Now both your custom function and built-in EmailValidator can be called with the same syntax.

for v in [custom_validator, EmailValidator()]:
    v(value) # <-----

As you can see, this implementation in Django is similar to what others have explained in their answers below. Can this be implemented in any other way? You could, but IMHO it will not be as readable or as easily extensible for a big framework like Django.

Justinjustina answered 28/4, 2011 at 23:33 Comment(3)
So if used correctly, it can make the code more readable. I assume if it is used on the wrong place, it would make the code very unreadable as well.Enclosure
This is an example of how it can be used, but not a good one in my opinion. There's no advantage in this case to having a callable instance. It would be better to have an interface/abstract class with a method, like .validate(); it's the same thing only more explicit. The real value of __call__ is being able to use an instance in a place where a callable is expected. I use __call__ most often when creating decorators, for example.Listed
@Listed Your last two sentences would make for a pretty nice answer to OP's question. Thanks!Erlking
P
41

I find it useful because it allows me to create APIs that are easy to use (you have some callable object that requires some specific arguments), and are easy to implement because you can use Object Oriented practices.

The following is code I wrote yesterday that makes a version of the hashlib.foo methods that hash entire files rather than strings:

# filehash.py
import hashlib


class Hasher(object):
    """
    A wrapper around the hashlib hash algorithms that allows an entire file to
    be hashed in a chunked manner.
    """
    def __init__(self, algorithm):
        self.algorithm = algorithm

    def __call__(self, file):
        hash = self.algorithm()
        with open(file, 'rb') as f:
            for chunk in iter(lambda: f.read(4096), ''):
                hash.update(chunk)
        return hash.hexdigest()


md5    = Hasher(hashlib.md5)
sha1   = Hasher(hashlib.sha1)
sha224 = Hasher(hashlib.sha224)
sha256 = Hasher(hashlib.sha256)
sha384 = Hasher(hashlib.sha384)
sha512 = Hasher(hashlib.sha512)

This implementation allows me to use the functions in a similar fashion to the hashlib.foo functions:

from filehash import sha1
print sha1('somefile.txt')

Of course I could have implemented it a different way, but in this case it seemed like a simple approach.

Petersen answered 28/4, 2011 at 21:5 Comment(7)
Again, closures ruin this example. pastebin.com/961vU0ay is 80% the lines and just as clear.Smalt
I'm not convinced it would always be just as clear to someone (e.g. perhaps someone who has only used Java). Nested functions and variable lookup/scope might be confusing. I suppose my point was that __call__ gives you a tool that lets you use OO techniques to solve problems.Petersen
Well, OP specifically asked why we should create a class with __call__, instead of e.g. using a different method name. Or (not mentioned in the question but the same question) why not use closures. (And on a side note, if someone's using Python and doesn't know closures, they should learn about them. I write code to be readable to people who know the language, and closures are a pretty fundamental concept, hardly exotic.)Smalt
I think the question "why use X over Y" when both provide equivalent functionality is terribly subjective. For some people the OO approach is easier to understand, for others the closure approach is. There's no compelling argument to use one over the other, unless you had a situation where you had to use isinstance or something similar.Petersen
@delnan Your closures example is less lines of code, but that it's just as clear is more difficult to argue.Eyelid
An example of where you would rather use a __call__ method instead of a closure is when you're dealing with the multiprocessing module, which uses pickling to pass information between processes. You can't pickle a closure, but you can pickle an instance of a class.Stinkstone
The closure approach also forfeits all the benefits of inheritance.Alban
S
39

__call__ is also used to implement decorator classes in python. In this case the instance of the class is called when the method with the decorator is called.

class EnterExitParam(object):

    def __init__(self, p1):
        self.p1 = p1

    def __call__(self, f):
        def new_f():
            print("Entering", f.__name__)
            print("p1=", self.p1)
            f()
            print("Leaving", f.__name__)
        return new_f


@EnterExitParam("foo bar")
def hello():
    print("Hello")


if __name__ == "__main__":
    hello()

program output:

Entering hello
p1= foo bar
Hello
Leaving hello
Sardonyx answered 15/9, 2014 at 9:8 Comment(0)
S
11

Yes, when you know you're dealing with objects, it's perfectly possible (and in many cases advisable) to use an explicit method call. However, sometimes you deal with code that expects callable objects - typically functions, but thanks to __call__ you can build more complex objects, with instance data and more methods to delegate repetitive tasks, etc. that are still callable.

Also, sometimes you're using both objects for complex tasks (where it makes sense to write a dedicated class) and objects for simple tasks (that already exist in functions, or are more easily written as functions). To have a common interface, you either have to write tiny classes wrapping those functions with the expected interface, or you keep the functions functions and make the more complex objects callable. Let's take threads as example. The Thread objects from the standard libary module threading want a callable as target argument (i.e. as action to be done in the new thread). With a callable object, you are not restricted to functions, you can pass other objects as well, such as a relatively complex worker that gets tasks to do from other threads and executes them sequentially:

class Worker(object):
    def __init__(self, *args, **kwargs):
        self.queue = queue.Queue()
        self.args = args
        self.kwargs = kwargs

    def add_task(self, task):
        self.queue.put(task)

    def __call__(self):
        while True:
            next_action = self.queue.get()
            success = next_action(*self.args, **self.kwargs)
            if not success:
               self.add_task(next_action)

This is just an example off the top of my head, but I think it is already complex enough to warrant the class. Doing this only with functions is hard, at least it requires returning two functions and that's slowly getting complex. One could rename __call__ to something else and pass a bound method, but that makes the code creating the thread slightly less obvious, and doesn't add any value.

Smalt answered 28/4, 2011 at 21:6 Comment(2)
It's probably useful to use the phrase "duck typing" (en.wikipedia.org/wiki/Duck_typing#In_Python) here -- you can mimic a function using a more complicated class object this way.Redivivus
As a related example, I've seen __call__ used to use class instances (instead of functions) as WSGI applications. Here's an example from "The Definitive Guide to Pylons": Using Instances of ClassesUnwritten
A
5

Class-based decorators use __call__ to reference the wrapped function. E.g.:

class Deco(object):
    def __init__(self,f):
        self.f = f
    def __call__(self, *args, **kwargs):
        print args
        print kwargs
        self.f(*args, **kwargs)

There is a good description of the various options here at Artima.com

Angarsk answered 28/4, 2011 at 21:12 Comment(1)
I rarely see class decorators though, as they require some nonobvious boilerplate code to work with methods.Smalt
A
4

IMHO __call__ method and closures give us a natural way to create STRATEGY design pattern in Python. We define a family of algorithms, encapsulate each one, make them interchangeable and in the end we can execute a common set of steps and, for example, calculate a hash for a file.

Adamo answered 2/11, 2012 at 16:23 Comment(0)
D
4

I just stumbled upon a usage of __call__() in concert with __getattr__() which I think is beautiful. It allows you to hide multiple levels of a JSON/HTTP/(however_serialized) API inside an object.

The __getattr__() part takes care of iteratively returning a modified instance of the same class, filling in one more attribute at a time. Then, after all information has been exhausted, __call__() takes over with whatever arguments you passed in.

Using this model, you can for example make a call like api.v2.volumes.ssd.update(size=20), which ends up in a PUT request to https://some.tld/api/v2/volumes/ssd/update.

The particular code is a block storage driver for a certain volume backend in OpenStack, you can check it out here: https://github.com/openstack/cinder/blob/master/cinder/volume/drivers/nexenta/jsonrpc.py

EDIT: Updated the link to point to master revision.

Diallage answered 22/3, 2016 at 15:22 Comment(1)
That's nice. I once used the same mechanism for traversing an arbitrary XML tree using attribute access.Kovach
L
2

I find a good place to use callable objects, those that define __call__(), is when using the functional programming capabilities in Python, such as map(), filter(), reduce().

The best time to use a callable object over a plain function or a lambda function is when the logic is complex and needs to retain some state or uses other info that in not passed to the __call__() function.

Here's some code that filters file names based upon their filename extension using a callable object and filter().

Callable:

import os

class FileAcceptor(object):
    def __init__(self, accepted_extensions):
        self.accepted_extensions = accepted_extensions

    def __call__(self, filename):
        base, ext = os.path.splitext(filename)
        return ext in self.accepted_extensions

class ImageFileAcceptor(FileAcceptor):
    def __init__(self):
        image_extensions = ('.jpg', '.jpeg', '.gif', '.bmp')
        super(ImageFileAcceptor, self).__init__(image_extensions)

Usage:

filenames = [
    'me.jpg',
    'me.txt',
    'friend1.jpg',
    'friend2.bmp',
    'you.jpeg',
    'you.xml']

acceptor = ImageFileAcceptor()
image_filenames = filter(acceptor, filenames)
print image_filenames

Output:

['me.jpg', 'friend1.jpg', 'friend2.bmp', 'you.jpeg']
Libbylibeccio answered 27/1, 2019 at 16:39 Comment(0)
C
2

I'm a novice, but here is my take: having __call__ makes composition easier to code. If f, g are instance of a class Function that has a method eval(self,x), then with __call___ one could write f(g(x)) as opposed to f.eval(g.eval(x)).

A neural network can be composed from smaller neural networks, and in pytorch we have a __call__ in the Module class:

Here's an example of where __call__ is used in practice: in pytorch, when defining a neural network (call it class MyNN(nn.Module) for example) as a subclass of torch.nn.module.Module, one typically defines a forward method for the class, but typically when applying an input tensor x to an instance model=MyNN() we just write model(x) as opposed to model.forward(x) but both give the same answer. If you dig into the source for torch.nn.module.Module here

https://pytorch.org/docs/stable/_modules/torch/nn/modules/module.html#Module

and search for __call__ one can eventually trace it back - at least in some cases - to a call to self.forward

import torch.nn as nn
import torch.nn.functional as F

class MyNN(nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1 = nn.Linear(784, 200)



    def forward(self, x):
        return F.ReLU(self.layer1(x))

x=torch.rand(10,784)
model=MyNN()
print(model(x))
print(model.forward(x))

will print the same values in the last two lines as the Module class has implemented __call___ so that's what I believe Python turns to when it sees model(x), and the __call__ which in turn eventually calls model.forward(x))

Crim answered 2/10, 2022 at 3:27 Comment(0)
A
1

Specify a __metaclass__ and override the __call__ method, and have the specified meta classes' __new__ method return an instance of the class, viola you have a "function" with methods.

Asyndeton answered 12/9, 2013 at 13:34 Comment(0)
R
1

We can use __call__ method to use other class methods as static methods.

    class _Callable:
        def __init__(self, anycallable):
            self.__call__ = anycallable

    class Model:

        def get_instance(conn, table_name):

            """ do something"""

        get_instance = _Callable(get_instance)

    provs_fac = Model.get_instance(connection, "users")             
Robichaux answered 5/12, 2016 at 8:21 Comment(0)
I
1

One common example is the __call__ in functools.partial, here is a simplified version (with Python >= 3.5):

class partial:
    """New function with partial application of the given arguments and keywords."""

    def __new__(cls, func, *args, **kwargs):
        if not callable(func):
            raise TypeError("the first argument must be callable")
        self = super().__new__(cls)

        self.func = func
        self.args = args
        self.kwargs = kwargs
        return self

    def __call__(self, *args, **kwargs):
        return self.func(*self.args, *args, **self.kwargs, **kwargs)

Usage:

def add(x, y):
    return x + y

inc = partial(add, y=1)
print(inc(41))  # 42
Ibbetson answered 24/2, 2018 at 15:20 Comment(0)
S
1

This is too late but I'm giving an example. Imagine you have a Vector class and a Point class. Both take x, y as positional args. Let's imagine you want to create a function that moves the point to be put on the vector.

4 Solutions

  • put_point_on_vec(point, vec)

  • Make it a method on the vector class. e.g my_vec.put_point(point)

  • Make it a method on the Point class. my_point.put_on_vec(vec)
  • Vector implements __call__, So you can use it like my_vec_instance(point)

This is actually part of some examples I'm working on for a guide for dunder methods explained with Maths that I'm gonna release sooner or later.

I left the logic of moving the point itself because this is not what this question is about

Scientism answered 31/3, 2020 at 22:13 Comment(0)
W
0

The function call operator.

class Foo:
    def __call__(self, a, b, c):
        # do something

x = Foo()
x(1, 2, 3)

The __call__ method can be used to redefined/re-initialize the same object. It also facilitates the use of instances/objects of a class as functions by passing arguments to the objects.

Wendeline answered 12/9, 2018 at 9:30 Comment(1)
When would it be useful? Foo(1, 2, 3) seems clearer.Terrific
C
0
import random


class Bingo:

def __init__(self,items):
    self._items=list(items)
    random.shuffle(self._items,random=None)


def pick(self):
    try:
        return self._items.pop()
    except IndexError:
        raise LookupError('It is empty now!')

def __call__(self):
    return self.pick()

b= Bingo(range(3))
print(b.pick())
print(b())
print(callable(b))

Now the output can be..(As first two answer keeps shuffling between [0,3])

2

1

True


You can see that Class Bingo implements _call_ method, an easy way to create a function like objects that have an internal state that must be kept across invocations like remaining items in Bingo. Another good use case of _call_ is Decorators. Decorators must be callable and it is sometimes convenient to "remember" something between calls of decorators. (i.e., memoization- caching the results of expensive computation for later use.)

Catmint answered 1/10, 2022 at 12:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.