I have below two functions:
def foo(n=50000):
return sum(i*i for i in range(n)) # just called sum() directly without
def bar(n=50000):
return sum([i*i for i in range(n)]) # passed constructed list to sum()
I was hoping that foo
will run faster then bar
but I have checked in ipython with %%timeit
that foo
is taking slightly longer then bar
In [2]: %%timeit
...: foo(50000)
...:
100 loops, best of 3: 4.22 ms per loop
In [3]: %%timeit
...: bar(50000)
...:
100 loops, best of 3: 3.45 ms per loop
In [4]: %%timeit
...: foo(10000000)
...:
1 loops, best of 3: 1.02 s per loop
In [5]: %%timeit
...: bar(10000000)
...:
1 loops, best of 3: 869 ms per loop
The difference increases as I increase value of n hence I tried to check function with dis.dis(foo)
and dis.dis(bar)
but it was identical.
So what would be the cause of such time difference between both methods?
As we can see, the for loop is slower than the list comprehension (9.9 seconds vs. 8.2 seconds). List comprehensions are faster than for loops to create lists. But, this is because we are creating a list by appending new elements to it at each iteration.
So what's the difference between Generator Expressions and List Comprehensions? The generator yields one item at a time and generates item only when in demand. Whereas, in a list comprehension, Python reserves memory for the whole list. Thus we can say that the generator expressions are memory efficient than the lists.
The list comprehension is 50% faster.
There are plenty of great answers about generators, so I won't elaborate on that.
Generators keep state. They are slightly slower if you do very fast operations (like using sum
, but if you use an I/O command there won't be much difference).
The upside for generators is that they don't load all the items to memory in advance, where lists does.
This is what happens when you iterate a list (in very high-level):
Compare that to a generator:
This extra step in the middle, is the diff in your tests.
So, generators are used commonly where you deal with huge amount of data that needs to be loaded on to memory. (There are more use-cases for generators ofcourse, like coroutines)
Do an expirement with huge files and a for loop printing the lines. At some point you will get out of memory exception when using lists. Then try using generators, they won't go out of memory..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With