Python Patterns: An Optimization Anecdote
python.org
python.org
import itertools
def f2_1(list):
return str(itertools.imap(chr, list))
and this: def f2_2(list):
return str(chr(c) for c in list)
They are both about twice as fast (in 2.7.2 CPython) as the suggested array solution (f2_1 performs slightly better for smaller lists), and their readability is rather significantly better. >>> import itertools
>>> def f2_1(list):
... return str(itertools.imap(chr, list))
...
>>> f2_1(range(10))
'<itertools.imap object at 0x10048e850>'
>>> def f2_2(list):
... return str(chr(c) for c in list)
...
>>> f2_2(range(10))
'<generator object <genexpr> at 0x10046b780>' ''.join(map(chr, list))
avoid the quadratic time of doing "string += something" (and also be a prettier solution IMO)?(In Python 2.x doing ''.join(chr(n) for n in list) might be a better solution to avoid the intermediate list created by map)
Remember that this essay is quite old (2002) and Python has changed significantly. [2]
[1] http://news.ycombinator.com/item?id=1859417
[2] http://keithdevens.com/weblog/archive/2002/Apr/10/AnOptimiza...
string = string + s
That is such a code smell I cringed every time I saw it.
Should append to list and join at the end (once). Which, I bet (I, or you, don't know anything until we actually profile), dumping the += is significant reason why last two examples where much faster.
$ python -V
Python 2.5.2
$ python -m timeit -s 'v=["a"]' 'v.append("a")'
1000000 loops, best of 3: 0.199 usec per loop
$ python -m timeit -s 's="a"' 's+="a"'
10000000 loops, best of 3: 0.127 usec per loop
The string append is actually FASTER now. Tried with strings of length 5 and it is still faster.
python -m timeit -s 'l = range(256);' '"".join([chr(i) for i in l])'
# 10000 loops, best of 3: 80.5 usec per loop
python -m timeit -s 'l = range(256); lchr = chr' '"".join([lchr(i) for i in l])'
# 10000 loops, best of 3: 75 usec per loop
python -m timeit -s 'import itertools; l = range(256); lchr = chr' '"".join(itertools.imap(chr, l))'
# 10000 loops, best of 3: 52.8 usec per loop
python -m timeit -s 'l = range(256); lchr = chr' '"".join(map(chr, l))'
# 10000 loops, best of 3: 48.9 usec per loop
python -m timeit -s 'l = range(256); lchr = chr' '"".join(lchr(i) for i in l)'
# 10000 loops, best of 3: 87.2 usec per loop
python -m timeit -s 'l = range(256); lchr = chr' '
s = ""
for i in l:
s += lchr(i)
'
# 10000 loops, best of 3: 64.2 usec per loop