__call__() allows the class instance to be called as a function
def __init__(self, n=0):
self.n = n
def __call__(self, x):
self.n += x
# create an instance and initialize data = 4
acc = Accumulator(4)
# remembers 4 and adds 5
print(acc(5)) # 9
# remembers 9 and adds 2
print(acc(2)) # 11
# remembers 11 and adds 9
print(acc(9)) # 20
# a bit more complex
print(acc(acc(10))) # 60
I wrote a code snippet some time ago with a base class for functors in python, click here. I use this class quite often to code reasonably-sized tasks which can be divided into smaller tasks sharing a temporary common state.
As an example, the following code defines a functor to count the number of lines of code (LOC) in the standard library.
# -*-coding: utf8-*-
from __future__ import (absolute_import, division,
__doc__ = '''
from functors import functor
import io, os
result = 0
for filename in self.python_source_files():
result += sum(1 for line in io.open(filename, 'rb'))
root = self.get_stdlib_dir()
for dir, subdirs, files in os.walk(root):
for f in files:
yield os.path.join(dir, f)
subdirs[:] = [d for d in subdirs if not d.endswith('-packages')]
from distutils.sysconfig import get_python_lib
if __name__ == '__main__':
""" my output -->
In my model, subclassing functor creates a callable instead of a class. Every time count_stdlib_LOC() is called, a new instance is created and the __call__() method is executed.
The advantage of having a functor instead of a function is that the task can be split into smaller tasks ran by other methods. This provides a handy way to encapsulate helper functions. These functions can share variables stored in self, which exist only during the execution of the task. The functor thus provides a short-lived namespace for the task.
These functors can be called recursively and different calls can be made by different threads. Object initialization is made in the __call__() method.
Another example using a typical closure function ...
a Python closure function mimics a functor
a functor can remember initial information
a functor to strip characters in chrs from string mystr
return ''.join(c for c in mystr if c not in chrs)
# name the functor, pass initial data
strip_punctuations = strip_characters(',;:.?!')
s = 'Please, strip punctuations from this string!'
# name another functor
strip_vowels = strip_characters('aeiouAEIOU')
s2 = 'Extra special consideration is given today'
Please strip punctuations from this string
xtr spcl cnsdrtn s gvn tdy