生成器表达式简介
生成器表达式是一种返回生成器对象的表达式。
基本上,生成器函数是一种包含 yield 语句的函数,它会返回一个生成器对象。
例如,下面定义了一个生成器函数:
def squares(length):
for n in range(length):
yield n ** 2
squares 生成器函数返回一个生成器对象,该对象可以生成从 0 到 length - 1 的整数的平方。
由于生成器对象是一个迭代器,你可以使用 for 循环来遍历其元素:
def squares(length):
for n in range(length):
yield n ** 2
for square in squares(5):
print(square)
输出:
0
1
4
9
16
而生成器表达式提供了一种更简洁的方式来返回生成器对象。
下面这个例子使用生成器表达式来生成从 0 到 4 的整数的平方:
squares = (n ** 2 for n in range(5))
由于 squares 是一个生成器对象,你可以像这样遍历它的元素:
for square in squares:
print(square)
如你所见,与使用函数定义生成器函数不同,你可以直接使用生成器表达式。
生成器表达式的语法类似于列表推导式(list comprehension)。例如,生成器表达式也支持以下复杂语法:
if条件语句- 多重嵌套循环
- 嵌套的推导式
但生成器表达式使用圆括号 (),而不是方括号 []。
生成器表达式 vs 列表推导式
下面展示了如何使用列表推导式生成从 0 到 4 的平方数:
square_list = [n ** 2 for n in range(5)]
而这是对应的生成器表达式:
square_generator = (n ** 2 for n in range(5))
语法差异
- 生成器表达式使用 圆括号
() - 列表推导式使用 方括号
[]
内存使用差异
- 列表推导式返回一个完整的列表,即一次性创建所有元素并全部加载到内存中。
- 生成器表达式返回一个生成器对象,它按需逐个生成元素,每次只将一个元素加载到内存中。
换句话说:
- 列表推导式是 “急切”(eager) 的;
- 生成器表达式是 “惰性”(lazy) 的。
可迭代对象 vs 迭代器
- 列表推导式返回的是一个可迭代对象(iterable),你可以多次遍历它。
- 生成器表达式返回的是一个迭代器(iterator),具体来说是一个惰性迭代器。一旦你完成一次完整遍历,它就会被“耗尽(exhausted)”,无法再次使用。
小结
- 使用 Python 生成器表达式可以便捷地创建生成器对象。
- 它在处理大数据或需要节省内存的场景中特别有用。
- 与列表推导式相比,生成器表达式更节省内存,但只能遍历一次。