What's the Difference Between Generator Expressions and List Comprehensions in Python?

Python generator expression vs. list comprehension

Generator expressions (Python 2.4+) and list comprehensions (Python 2.0+) differ in the following ways:

Syntax

Syntactically, the difference between the two is that generator expressions are wrapped in parentheses and list comprehensions are wrapped in squared brackets:

# generator expression
(item for item in iterable)
# list comprehension
[item for item in iterable]

Consider, for example, the following where numbers are squared using generator expression:

squares = list(n ** 2 for n in range(5))
print(squares) # [0, 1, 4, 9, 16]

This is equivalent to the following:

def GenSquare(num):
    for n in range(num):
        yield(n ** 2)

squares = list(GenSquare(5))

print(squares) # [0, 1, 4, 9, 16]

The same example (of squaring numbers) can be written as list comprehension, for example, like so:

squares = [n ** 2 for n in range(5)]
print(squares) # [0, 1, 4, 9, 16]

This is equivalent to the following:

squares = list(map(lambda n: n ** 2, range(5)))
print(squares) # [0, 1, 4, 9, 16]

It can also be written in a loop, like so:

squares = []

for n in range(5):
    squares.append(n ** 2)

print(squares) # [0, 1, 4, 9, 16]

Return Type

Generator expressions return a generator object, while list comprehensions return a new list:

# generator syntax
squares = (n ** 2 for n in range(5))
print(squares) # <generator object <genexpr> at ...>
# list comprehension
squares = [n ** 2 for n in range(5)]
print(squares) # [0, 1, 4, 9, 16]

To return a list with generator syntax, you have to explicitly wrap the resulting generator object in a list, for example, like so:

# generator syntax
squares = list(n ** 2 for n in range(5))
print(squares) # [0, 1, 4, 9, 16]

Since generator expression return a generator object, it won't support list functions/operations (such as indexing, slicing, etc.) unless you explicitly convert it to a list.

Operation

Generator expressions are more memory efficient than list comprehensions. This is because list comprehension loads the entire list in memory, whereas a generator expression only loads one value in memory at a time. For example, you can check how much memory each of these use by using the sys.getsizeof() method:

from sys import getsizeof

ge = (n for n in range(5000))

ge_size = getsizeof(ge)
print(ge_size) # 112

lc = [n for n in range(5000)]

lc_size = getsizeof(lc)
print(lc_size) # 43032

This means that you can use generator expressions for very large, even infinite, sequences.


Hope you found this post useful. It was published . Please show your love and support by sharing this post.