上一节(6.3生产者/消费者)|下一节(7个高级主题)6.4更多关于生成器本节介绍其他与生成器相关的主题,包括生成器表达式和itertools模块。生成器表达式生成器表达式可以理解为生成器版本的列表理解:>>>a=[1,2,3,4]>>>b=(2*xforxina)>>>b>>>foriinb:...print(i,end='')...2468>>>generatorexpression和listlistcomprehension区别:唯一有用的目的是不构造alist一旦被消费就迭代,不能重复使用生成器表达式语法:(foriinsif)生成器表达式也可以作为函数参数:sum(x*xforxina)生成器表达式可以应用于任何迭代:>>>a=[1,2,3,4]>>>b=(x*xforxina)>>>c=(-xforxinb)>>>foriinc:...print(i,end='')...-1-4-9-16>>>代码中的生成器表达式中的主要用途之一是对序列进行计算,但只使用一次结果。例如,跳过文件中的所有注释。f=open('somefile.txt')lines=(lineforlineinfifnotline.startswith('#'))forlineinlines:...f.close()使用生成器,代码运行速度更快并且占用更少的内存,类似于应用于流的过滤器。WhyUseGenerators很多问题都表现为迭代的形式,遍历集合中的元素,进行一些操作(如查找、替换、修改等)。处理流水线可以应用于各种数据处理问题。更高效的内存只在需要时生成值。不要构建庞大的列表。对流数据进行操作。生成器表达式通过将迭代与使用它的代码分开来鼓励代码重用。构建迭代函数的工具箱,混合和匹配(mix-n-match)各种工具。itertools模块itertools是Python自带的库模块,包含各种旨在帮助开发迭代器/生成器的函数。itertools.chain(s1,s2)itertools.count(n)itertools.cycle(s)itertools.dropwhile(predicate,s)itertools.groupby(s)itertools.ifilter(predicate,s)itertools.imap(function,s1,...sN)itertools.repeat(s,n)itertools.tee(s,ncopies)itertools.izip(s1,...,sN)itertools模块中的所有函数迭代处理数据。此外,这些函数实现了各种迭代模式。有关生成器的更多信息,请参阅PyCon'08的系统程序员生成器技巧教程。练习在前面的练习中,我们编写了代码来监视写入日志文件的数据并将其解析为一系列行。本练习将基于上一个练习的代码,因此请确保Data/stocksim.py仍在运行。练习6.13:生成器表达式生成器表达式是列表推导式的生成器版本。示例:>>>nums=[1,2,3,4,5]>>>squares=(x*xforxinnums)>>>squaresat0x109207e60>>>>forninsquares:...print(n)...1491625与列表理解不同,生成器表达式只能使用一次。因此,如果在遍历生成器中的所有元素之后再遍历生成器,你将一无所获。>>>forninsquares:...print(n)...>>>练习6.14:函数参数中的生成器表达式有时生成器表达式用作函数参数。虽然这看起来很奇怪,但试试这个实验:>>>nums=[1,2,3,4,5]>>>sum([x*xforxinnums])#Alistcomprehension55>>>sum(x*xforxinnums)#Ageneratorexpression55>>>在上面的例子中,如果你正在操作巨大的列表,使用生成器的第二个版本将占用更少的内存。在portfolio.py文件中,我们执行一些与列表相关的计算,尝试用生成器表达式替换它们。练习6.15:简化代码通常,简单的生成器函数可以用生成器表达式代替。例如,与其编写这样的函数:deffilter_symbols(rows,names):forrowinrows:ifrow['name']innames:yieldrow,而是使用生成器表达式:rows=(rowforrowinrowsifrow['name']innames)请修改ticker.py程序以适当地使用生成器表达式。目录|上一节(6.3生产者/消费者)|NextSection(7AdvancedTopics)注:完整翻译见https://github.com/codists/practical-python-zh