2008-12-13 50 views

回答

94

你了解列表解析吗?如果是这样,一个生成器表达式就像列表理解一样,但不是找到你感兴趣的所有项目并将它们打包到列表中,而是等待,并逐个从表达式中逐项生成每个项目。

>>> my_list = [1, 3, 5, 9, 2, 6] 
>>> filtered_list = [item for item in my_list if item > 3] 
>>> print filtered_list 
[5, 9, 6] 
>>> len(filtered_list) 
3 
>>> # compare to generator expression 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> print filtered_gen # notice it's a generator object 
<generator object at 0xb7d5e02c> 
>>> len(filtered_gen) # So technically, it has no length 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: object of type 'generator' has no len() 
>>> # We extract each item out individually. We'll do it manually first. 
... 
>>> filtered_gen.next() 
5 
>>> filtered_gen.next() 
9 
>>> filtered_gen.next() 
6 
>>> filtered_gen.next() # Should be all out of items and give an error 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
StopIteration 
>>> # Yup, the generator is spent. No values for you! 
... 
>>> # Let's prove it gives the same results as our list comprehension 
... 
>>> filtered_gen = (item for item in my_list if item > 3) 
>>> gen_to_list = list(filtered_gen) 
>>> print gen_to_list 
[5, 9, 6] 
>>> filtered_list == gen_to_list 
True 
>>> 

因为发生器表达式一次只能产生一个项目,所以会导致内存使用量大大节省。生成器表达式最适用于需要一次取一个项目的场景,根据该项目进行大量计算,然后转到下一个项目。如果您需要多个值,则还可以使用生成器表达式并一次抓取几个值。如果您在程序开始之前需要所有的值,请改为使用列表理解。

12

发电机理解是一个列表理解的懒惰版本。

它就像除了它即具有next()方法,将产生下一个元素的对象返回迭代代替列表中的一个列表中理解。

如果你不熟悉列表推导看到here和发电机见​​。

4

列表/发电机理解是一个结构,它可用于从现有的创建一个新的列表/发电机。

比方说,你要生成从1到10每个数字的平方列表您可以在Python做到这一点:

>>> [x**2 for x in range(1,11)] 
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 

这里,range(1,11)生成列表[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],但range功能不Python 3.0之前的生成器,因此我使用的构造是列表理解。

如果我想创建一个发电机,做同样的事情,我可以做这样的:

>>> (x**2 for x in xrange(1,11)) 
<generator object at 0x7f0a79273488> 

在Python 3,但是,range是发电机,所以胜负只取决于语法你使用(方括号或圆括号)。

+1

这是错误的。外部表达是否是生成器与内部表达是否无关。显然,从列表中获取元素的生成器表达式通常没有多少意义,您可以这样做。 – Antimony 2013-03-05 23:46:37

2

发生器理解为具有一定的结构中产生的发电机的简单方法。假设你想要一个generator,它可以逐个输出your_list中的所有偶数。如果使用该函数的风格创建它,它会是这样:当你调用next(evens)

evens = (number for number in your_list if number % 2 == 0) 

在这两种情况下,:

def allEvens(L): 
    for number in L: 
     if number % 2 is 0: 
      yield number 

evens = allEvens(yourList) 

你可以实现与这台发电机理解表达相同的结果获得your_list中的下一个偶数。

0

发电机的理解是创造iterables,像这对移动资源的光标的方法。如果您知道mysql游标或mongodb游标,您可能会意识到整个实际数据不会一次加载到内存中,而是一次加载一次。你的光标来回移动,但内存中总是有一行/列表元素。

总之,通过使用生成器理解,你可以很容易地在python中创建光标。

0

发电机理解的又如:

print 'Generator comprehensions' 

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

for x in sq_num(10): 
    print x