Reputation: 10172
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
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