How exactly does a generator comprehension work?
生成器理解有什么作用?它是如何工作的?我找不到关于它的教程。
你明白清单的理解吗?如果是这样,生成器表达式就像一个列表理解,但它不会查找所有感兴趣的项并将它们打包到列表中,而是等待,并从表达式中逐个生成每个项。
python2版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | >>> 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 >>> |
python3版本:
将
因为生成器表达式一次只需要生成一个项,所以可以大大节省内存使用量。生成器表达式在需要一次获取一个项、基于该项进行大量计算,然后转到下一个项的情况下最有意义。如果需要多个值,还可以使用生成器表达式,一次获取几个值。如果在程序进行之前需要所有值,请使用列表理解。
生成器理解是列表理解的懒惰版本。
它就像一个列表理解,只是它返回一个迭代器而不是列表,即一个带有next()方法的对象,该方法将生成下一个元素。
如果您不熟悉列表理解,请参见此处,对于生成器,请参见此处。
列表/生成器理解是一种构造,您可以使用它从现有列表/生成器创建新的列表/生成器。
假设您希望生成从1到10的每个数字的平方列表。在python中可以这样做:
1 2 | >>> [x**2 for x in range(1,11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] |
这里,
如果我想创建一个执行相同操作的生成器,我可以这样做:
1 2 | >>> (x**2 for x in xrange(1,11)) <generator object at 0x7f0a79273488> |
然而,在Python3中,
生成器理解是创建具有特定结构的生成器的简单方法。假设您想要一个逐条输出
1 2 3 4 5 6 | def allEvens( L ): for number in L: if number % 2 is 0: yield number evens = allEvens( yourList ) |
使用这个生成器理解表达式可以获得相同的结果:
1 | evens = ( number for number in your_list if number % 2 == 0 ) |
在这两种情况下,当您调用
发电机理解的另一个例子:
1 2 3 4 5 6 7 8 | 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 |
生成器理解是一种创建iterables的方法,类似于在资源上移动的光标。如果您知道mysql cursor或mongodb cursor,那么您可能会意识到整个实际数据不会一次加载到内存中,而是一次加载一个。光标来回移动,但内存中始终有一个单行/列表元素。
简而言之,通过使用生成器理解,您可以轻松地在Python中创建游标。