当前位置: 首页 > 科技观察

长谈Python生成器

时间:2023-03-21 17:54:03 科技观察

ython生成器什么是一句话解释:包含yield关键字的函数就是生成器,它的返回值是一个生成器对象。我简单画了一个示意图:yield就相当于return。当函数遇到yield时,它会暂停,保存当前信息,并返回yield的值。下次执行next()时,将从当前位置继续执行。比较有意思的是,曾经有人建议生成器函数不要用def,而应该发明一个新的关键字,比如gen,但是Python之父Guido并不认同这一点。生成器函数的工作原理首先用一个简单的例子来说明生成器的行为:#定义一个生成器>>>defgen_123():...yield1...yield2...yield3...#Thegenerator本身是一个Function>>>gen_123#返回值是一个generator对象>>>gen_123()#generator也是一个iterator>>>foriingen_123():...print(i)...123#验证生成器也是迭代器,定义迭代器g>>>g=gen_123()#可以通过next()获取yield生成的下一个元素>>>next(g)1>>>next(g)2>>>next(g)3>>>next(g)Traceback(mostrecentcallast):File"",line1,inStopIteration生成器的原理是:生成器函数将创建一个生成器对象。当生成器传递给next()函数时,生成器函数会执行函数定义体中的下一条yield语句,返回输出值,并在当前位置暂停。当返回函数的定义体时,外层生成器对象将抛出StopIteration异常。yield关键字一般与for循环结合使用,在for循环中隐式调用next()函数。生成器的作用其实就是解决内存问题。比如我们都知道Python的正则表达式有一个re.findall()函数,它会一次性把所有匹配到的元素写入内存。如果匹配的数据很多,会占用大量内存。为了解决这个问题,Python3有一个re.finditer()函数,它返回一个generator,在取值的时候生成数据放入内存,可以节省大量内存。标准库中的生成器函数在了解标准库中可用的内容的情况下实现生成器,否则可能会重新发明轮子。有些是内置的,有些在itertools模块中,有些在functools模块中。用于过滤的生成器函数从输入可迭代对象中生成元素的子集,而无需修改元素本身。地图的生成器函数对单个输入可迭代的元素执行计算并返回结果。组合多个可迭代对象的生成器函数从输入可迭代对象中生成元素。将输入的每个元素扩展为多个输出元素的生成器函数从单个元素产生多个值,扩展输入可迭代。用于重新排列元素的生成器函数产生输入可迭代中的所有元素,但以某种方式重新排列。yieldfromyieldfrom是Python3.3中的新语法,其作用是将不同的生成器组合在一起。例如,生成器函数需要生成由另一个生成器生成的值。传统的解决方案是使用for循环:defchain(*iterables):foritiniterables:foriinit:yieldis="ABC"t=tuple(range(3))print(list(chain(s,t)))#["A","B","C",0,1,2]改为yieldfrom:defchain(*iterables):foritiniterables:yieldfromi完全取代内层for循环。参考资料:《流畅的Python》Chapter14IterableObjects,IteratorsandGeneratorshttps://www.runoob.com/python3/python3-iterator-generator.htmlAuthor