Ruud van der Ham
2 min readNov 11, 2019

--

I am afraid the timing conclusion from this article

1*8xC0khI4StoWcJSSuLKERg.png959×234

is completely wrong.
In the case of the Using Generators case the author just makes the generator, but doesn’t consume it. If you consume it (i.e. do something with it), the timings are completely different. As a test I just sum the list/generator and get:
The normal approach: 23.1058 s
Using generators: 22.9009 s
So the list solution is just marginally slower (and not even consistently). Of course, the memory requirements are significantly different.

And the author missed the the Pythonic approach to building a list with a list comprehension (and not append), which turns out to be consistently faster than the generator approach.

What most Python programmers would do in this case is not build a generator with yield but use a generator expression, which, to my surprise, turns out to be slower than the proposed generator method.

I have found that that in general list comprehensions are faster than generator (expressions).
So my advice: for performance reasons: use list expressions and not generators/generator expressions. Of course, memory usage might require a generator (expression).

Here is my program to demonstrate it all:

import time
import sys
def check_even_list_append(numbers):
even = []
for num in numbers:
if num % 2 == 0:
even.append(num * num)
return even
def check_even_generator_yield(numbers):
for num in numbers:
if num % 2 == 0:
yield num * num
def check_even_list_comprehension(numbers):
return [num * num for num in numbers if num % 2 == 0]
def check_even_generator_expression(numbers):
return (num * num for num in numbers if num % 2 == 0)
size = 100000000for check_even in (
check_even_list_append,
check_even_generator_yield,
check_even_list_comprehension,
check_even_generator_expression,
):
t1 = time.time()
cubes = check_even(range(size))
result = sum(cubes) # this is the big difference with the original article
t2 = time.time()
print(f"function: {check_even.__name__:31} duration:{t2 - t1:8.4f} s size:{sys.getsizeof(cubes):10}")

With a sample output (on other systems the timings might be quite different):

function: check_even_list_append          duration: 23.1058 s size: 424076264
function: check_even_generator_yield duration: 22.9009 s size: 120
function: check_even_list_comprehension duration: 21.2778 s size: 424076264
function: check_even_generator_expression duration: 24.0002 s size: 120

--

--