Python介绍
示例
生成器表达式类似于列表,字典和集合推导,但用括号括起来。当括号用作函数调用的唯一参数时,括号不必存在。
expression = (x**2 for x in range(10))
本示例生成10个第一个完美正方形,包括0(其中x=0)。
生成器函数与常规函数类似,不同之处在于生成器函数yield的主体中具有一个或多个语句。这些函数不能有return任何值(但是,return如果您想尽早停止生成器,则可以使用empty)。
def function(): for x in range(10): yield x**2
该生成器函数等效于先前的生成器表达式,但输出相同。
注意:所有生成器表达式都具有自己的等效函数,反之亦然。
如果两个括号都可以重复,则可以在不带括号的情况下使用生成器表达式:
sum(i for i in range(10) if i % 2 == 0) #输出:20 any(x = 0 for x in foo) #输出:取决于foo,是对还是错 type(a > b for a in foo if a % 2 == 1) #Output: <class 'generator'>
代替:
sum((i for i in range(10) if i % 2 == 0)) any((x = 0 for x in foo)) type((a > b for a in foo if a % 2 == 1))
但不是:
fooFunction(i for i in range(10) if i % 2 == 0,foo,bar) return x = 0 for x in foo barFunction(baz, a > b for a in foo if a % 2 == 1)
调用generator函数将生成一个generator对象,以后可以对其进行迭代。与其他类型的迭代器不同,生成器对象只能被遍历一次。
g1 = function() print(g1) # Out: <generator object function at 0x1012e1888>
请注意,生成器的主体不会立即执行:当您function()在上面的示例中调用时,它会立即返回生成器对象,甚至不执行第一个print语句。与返回列表的函数相比,这允许生成器消耗更少的内存,并且允许创建生成无限长序列的生成器。
因此,生成器经常用于数据科学以及涉及大量数据的其他环境中。另一个优点是,其他代码可以立即使用生成器产生的值,而不必等待完整的序列产生。
但是,如果您需要多次使用生成器生成的值,并且生成它们的成本要比存储高,那么将list生成的值存储为a可能比重新生成序列更好。有关更多详细信息,请参见下面的“重置生成器”。
通常,生成器对象用于循环或需要可迭代的任何函数中:
for x in g1: print("Received", x) #输出: #收到0 #已收到1 #收到了4 #收到9 #已收到16 #收到25 #收到36 #收到了49 #收到64 #收到81 arr1 = list(g1) #arr1=[],因为上面的循环已经消耗了所有值。 g2 = function() arr2 = list(g2) #arr2=[0,1,4,9,16,25,36,49,64,81]
由于生成器对象是迭代器,因此可以使用该next()函数手动对其进行迭代。这样做将在每次后续调用中一一返回生成的值。
在幕后,每次调用next()生成器时,Python都会在生成器函数的主体中执行语句,直到命中下一条语句为止yield。此时,它返回yield命令的参数,并记住发生该事件的位置。next()从该点再次调用将恢复执行,并继续直到下yield一条语句。
如果Python在没有遇到更多yields的StopIteration情况下到达了生成器函数的末尾,则会引发一个异常(这是正常的,所有迭代器的行为均相同)。
g3 = function() a = next(g3) #a变为0 b = next(g3) #b变成1 c = next(g3) #c变成2 ... j = next(g3) #引发StopIteration,j保持未定义
请注意,在Python2中,生成器对象具有可用于手动迭代生成的值的方法。在Python3中,此方法已被所有迭代器的标准所取代。.next().__next__()
重置发电机
请记住,你只能通过迭代由发电机产生的对象一次。如果您已经遍历脚本中的对象,则进一步尝试将产生None。
如果需要多次使用生成器生成的对象,则可以再次定义生成器函数并再次使用它,或者,可以在首次使用时将生成器函数的输出存储在列表中。如果要处理大量数据,重新定义生成器功能将是一个不错的选择,并且存储所有数据项的列表将占用大量磁盘空间。相反,如果最初生成项目的成本很高,则您可能希望将生成的项目存储在列表中,以便重新使用它们。