你是否理解列表推导式?如果是这样,那么生成器表达式就像一个列表推导式,但不是找到所有感兴趣的项并将它们打包成列表,而是等待,并逐一从表达式中生成每个项。
>>> 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 <genexpr> at 0x7f2ad75f89e0>
>>> 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.
...
>>> next(filtered_gen)
5
>>> next(filtered_gen)
9
>>> next(filtered_gen)
6
>>> next(filtered_gen) # 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
>>>
由于生成器表达式一次只需产生一个项目,因此它可以大大节省内存使用。生成器表达式在需要逐个取出一个项目,基于该项目进行大量计算,然后转到下一个项目的情况下最有意义。如果您需要多个值,则也可以使用生成器表达式并一次取几个值。如果程序在继续之前需要所有值,请改用列表理解。
next(...)
而不是.__next__()
。 - Todd Sewellfirst = next(gen)
和 second = next(gen)
来获取多个值以供使用。还有一个很棒的 more-itertools
包,它也有很多方便的工具,比如 chunked
。 - CrazyChuckyList/generator comprehension是一种构造方法,您可以使用它从现有列表/生成器创建一个新的列表/生成器。
假设你想要生成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]
,但是在 Python 3.0 之前,range
函数不是生成器,因此我使用的是列表推导式。
如果我想创建一个执行相同操作的生成器,可以像这样实现:
>>> (x**2 for x in xrange(1,11))
<generator object at 0x7f0a79273488>
然而在Python 3中,range
是一个生成器,因此其结果仅取决于您使用的语法(方括号或圆括号)。
生成器推导式是创建具有特定结构的生成器的简单方法。假设您想要一个generator
,它逐个输出your_list
中的所有偶数。如果您使用函数样式创建它,则会像这样:
def allEvens( L ):
for number in L:
if number % 2 is 0:
yield number
evens = allEvens( yourList )
evens = ( number for number in your_list if number % 2 == 0 )
next(evens)
时,您将获得your_list
中下一个偶数。生成器表达式的另一个例子:
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
生成器推导式是创建可迭代对象的一种方法,类似于在资源上移动的光标。如果您了解mysql游标或mongodb游标,您可能会意识到整个实际数据不会一次性加载到内存中,而是逐一加载一个。您的光标来回移动,但内存中总是有一个行/列表元素。
简而言之,通过使用生成器推导式,您可以轻松地在Python中创建游标。
generator_composition_object = (num**3 for num in range(5))
print(generator_composition_object)
这将给出类型为生成器的对象的地址。我们还可以在其中使用next()等功能。
生成器与列表相同,唯一的区别在于,在列表中,我们一次性获取列表的所有所需数字或项目,但在生成器中,所需数字逐个产生。因此,为了获取所需的项目,我们必须使用for循环来获取所有所需的项目。
#to get all the even numbers in given range
def allevens(n):
for x in range(2,n):
if x%2==0:
yield x
for x in allevens(10)
print(x)
#output
2
4
6
8