4 ms·
> the list comprhension surely runs faster than the for loop How much quicker? It isn't too significant, is it? I mean, we have two O(1) operations to worry ab
by odonnellryan 11y ago
> the list comprhension surely runs faster than the for loop
How much quicker? It isn't too significant, is it? I mean, we have two O(1) operations to worry about, I suppose: lookup and appending to the list.
- dr_zoidberg 11y agoIt depends on what the for loop does, but main difference is that a for loop runs "interpreted", vs the list comprehensions that runs "compiled" (or in "C-space"). The list comprehension has some additional benefits, the pattern: squares = [] for x in xrange(100): squares.append(x*x) in which you have an append call on every iteration is a mess because it may lead to a lot of memory operations which are really unnecesary. The LC version of it is much shorter an runs faster, because the memory allocation is handled differently: squares = [x*x for x in xrange(100)] Append may be O(1) but in some cases it doesn't behave nicely. On large lists, you can hit spots in which it reallocates parts of the list in memory, leading to weird slowdowns. Timings from ipython on a Windows 8 64bit Python 2.7.9 machine: In [12]: def f1(): ....: sq = [] ....: for x in xrange(100): ....: sq.append(x*x) ....: return sq ....: In [13]: def f2(): ....: return [x*x for x in xrange(100)] ....: In [14]: %timeit f1() 10000 loops, best of 3: 20.7 µs per loop In [15]: %timeit f2() 100000 loops, best of 3: 11.9 µs per loop
- odonnellryan 11y agoVery interesting! That's a pretty good speed-up! Makes me reconsider writing some "complex" LC as for-loops.
- dr_zoidberg 11y agoBear in mind that the LC will take all the memory needed at once, and that can bring some problems. You can also use a generator expresion (similar to a LC, but you use parenthesis instead of brackets) to avoid this problem, if you're expecting an iterable object and have no further need for the values after the computation is done: In [1]: (x*x for x in xrange(100)) Out[1]: <generator object <genexpr> at 0x0000000003558438> And the generator expression could be used inside a for loop in cases where de LC would be awkward or take more time (because you have to allocate memory for a billion numbers all at once, just to check those that are meet a certain requirement).