Emanuele Paolini
Emanuele Paolini

Reputation: 10172

how to define a constant function

In the documentation I found

The function int() which always returns zero is just a special case of constant functions. A faster and more flexible way to create constant functions is to use itertools.repeat() which can supply any constant value (not just zero):

def constant_factory(value): 
   return itertools.repeat(value).next

d = defaultdict(constant_factory('<missing>'))
d.update(name='John', action='ran')
'%(name)s %(action)s to %(object)s' % d 

'John ran to <missing>'

Why don't simply use a lambda function to get a constant function?

Upvotes: 3

Views: 5930

Answers (1)

Blckknght
Blckknght

Reputation: 104792

The itertools.repeat class is written in C, and it is a bit faster than using a function written in Python. Here's some testing I did with different constant value function implementations, using the timeit module:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17)
[MSC v.1600 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import timeit
>>> import itertools
>>> itertools_version = itertools.repeat(10).__next__
>>> lambda_version = lambda:10
>>> def function_version():
    return 10
>>> def constant_factory(n):
    return itertools.repeat(n).__next__
>>> factory_version = constant_factory(10)
>>> timeit.timeit("for i in range(100): f()",
                  setup="from __main__ import itertools_version as f")
7.115707915662512
>>> timeit.timeit("for i in range(100): f()",
                  setup="from __main__ import lambda_version as f")
11.479014911317307
>>> timeit.timeit("for i in range(100): f()",
                  setup="from __main__ import function_version as f")
11.561433023257619
>>> timeit.timeit("for i in range(100): f()",
                  setup="from __main__ import factory_version as f")
7.166709032038568

However, think carefully if this modest performance increase is worth it for your situation. If this is not performance critical code, you should use whichever implementation you think is easiest to understand when you read it later.

If you're only going to use the constant function once, I think a lambda would be perfectly appropriate. If it's something you'll use often, a named function is perhaps better. If it's being called in the inner loop of some of the most time-sensitive logic you have, then use a bound method of an itertools.repeat object.

Upvotes: 3

Related Questions