Does anybody have a good example of a Functor in Python?

Recommended Answers

All 6 Replies

When you say "functor" are you using the term in the C++ sense (i.e. a callable object) or something else?

And would a good example be the most simple one that shows you how to create one or something that shows you where they'd be useful?

Here is a typical example:

class Accumulator(object):
    '''
    remembers self.n
     __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
        return self.n

# 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.

#!/usr/bin/env python
# -*-coding: utf8-*-
from __future__ import (absolute_import, division,
                        print_function, unicode_literals)

__doc__ = '''
'''
from functors import functor
import io, os

class count_stdlib_LOC(functor):
    def __call__(self):
        result = 0
        for filename in self.python_source_files():
            result += sum(1 for line in io.open(filename, 'rb'))
        return result

    def python_source_files(self):
        root = self.get_stdlib_dir()
        for dir, subdirs, files in os.walk(root):
            for f in files:
                if f.endswith('.py'):
                    yield os.path.join(dir, f)
            subdirs[:] = [d for d in subdirs if not d.endswith('-packages')]

    def get_stdlib_dir(self):
        from distutils.sysconfig import get_python_lib
        return get_python_lib(standard_lib=True)

if __name__ == '__main__':
    print(count_stdlib_LOC())

""" my output -->
242389
"""

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.

Edit: bugfix

The class Accumulator is an example of a functor for closure.

Another example using a typical closure function ...

''' func_functor_strip_char1.py
a Python closure function mimics a functor
a functor can remember initial information
'''

def strip_characters(chrs):
    '''
    a functor to strip characters in chrs from string mystr
    '''
    def inner(mystr):
        return ''.join(c for c in mystr if c not in chrs)
    return inner


# name the functor, pass initial data
strip_punctuations = strip_characters(',;:.?!')

s = 'Please, strip punctuations from this string!'
print(strip_punctuations(s))

# name another functor
strip_vowels = strip_characters('aeiouAEIOU')

s2 = 'Extra special consideration is given today'
print(strip_vowels(s2))

''' result...
Please strip punctuations from this string
xtr spcl cnsdrtn s gvn tdy
'''

I think I get the idea.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.