生成器表达式与列表理解

时间:2020-03-05 18:48:46  来源:igfitidea点击:

什么时候应该使用生成器表达式,什么时候应该在Python中使用列表推导?

# Generator expression
(x*2 for x in range(256))

# List comprehension
[x*2 for x in range(256)]

解决方案

回答

当结果需要多次迭代或者速度至关重要时,请使用列表推导。使用范围较大或者无穷大的生成器表达式。

回答

遍历生成器表达式或者列表理解将执行相同的操作。但是,列表理解将首先在内存中创建整个列表,而生成器表达式将在运行中创建项目,因此我们可以将其用于很大(甚至无限!)的序列。

回答

John的答案很好(当我们要迭代多次时,列表理解会更好)。但是,还应注意,如果要使用任何列表方法,都应使用列表。例如,以下代码将不起作用:

def gen():
    return (something for something in get_some_stuff())

print gen()[:2]     # generators don't support indexing or slicing
print [5,6] + gen() # generators can't be added to lists

基本上,如果我们要做的只是迭代一次,则使用生成器表达式。如果我们要存储和使用生成的结果,那么列表理解可能会更好。

由于性能是选择彼此的最常见原因,所以我的建议是不要担心它,而只选择其中一个即可。如果我们发现程序运行速度太慢,那么只有这样,我们才应该回去担心调整代码。

回答

有时,我们可以从itertools中使用tee函数,它会为同一生成器返回多个迭代器,这些迭代器可以独立使用。

回答

生成器表达式的好处是它使用较少的内存,因为它不会立即构建整个列表。当列表是中间变量时,最好使用生成器表达式,例如对结果求和或者根据结果创建字典。

例如:

sum(x*2 for x in xrange(256))

dict( ((k, some_func(k) for k in some_list_of_keys) )

这样做的好处是列表不会完全生成,因此使用的内存很少(而且应该更快)

但是,当所需的最终产品是列表时,应该使用列表推导。我们将不会使用生成器表达式保存任何内存,因为我们需要生成的列表。我们还可以获得能够使用任何列表功能(如已排序或者倒序)的好处。

例如:

reversed( [x*2 for x in xrange(256)] )