类别|上一节(6.2自定义迭代)|NextSection(6.4ProducerExpression)6.3Producers,ConsumersandPipelineBuilders设置各种生产者/消费者在生产者/消费者问题和数据流管道中很有用。本节对此进行讨论。生产者消费者问题生成器与各种形式的生产者消费者问题密切相关。#Producerdeffollow(f):...whileTrue:...yieldline#Producesvaluein`line`below...#Consumerforlineinfollow(f):#从上面的`yield`消耗值...yield该语句产生由for语句消耗的值。生成器管道您可以使用生成器的这一方面来设置进程管道(类似于Unix管道)。producer→processing→processing→consumer流程??管道包括初始数据生产者、中间处理阶段和最终消费者。producer→processing→processing→consumerdefproducer():...yielditem...通常,生产者是一个生成器,尽管其他序列表也是可能的。yield将数据馈送到管道中。producer→processing→processing→consumerdefconsumer(s):foritemins:...consumer是一个for循环,取数据(译注:items)并对数据进行一些操作。producer→processing→processing→consumerdefprocessing(s):foritemins:...yieldnewitem...中间处理阶段同时消费和生产数据。他们可能会修改数据流,或者他们可能会过滤数据流(丢弃数据)。producer→processing→processing→consumerdefproducer():...yielditem#yields由`processing`接收的项目...defprocessing(s):foritemins:#Comesfromthe`producer`...yieldnewitem#yieldsanewitem...defconsumer(s):foritemins:#Comesfromthe`processing`...设置管道的代码如下:a=producer()b=processing(a)c=consumer(b)你会发现数据逐渐流向不同的函数。练习对于这个练习,stocksim.py程序仍然需要在后台运行。此外,您将使用上一个练习(译注:练习6.7)中编写的follow()函数。练习6.8:创建一个简单的管道让我们看看管道的概念。请创建以下函数:>>>deffilematch(lines,substr):forlineinlines:ifsubstrinline:yieldline>>>filematch()该函数与练习中的第一部分几乎相同上一节除了文件不再打开。生成器示例的作用完全相同——只是对作为参数给出的行序列进行操作。现在,尝试以下操作:>>>fromfollowimportfollow>>>lines=follow('Data/stocklog.csv')>>>ibm=filematch(lines,'IBM')>>>forlineinibm:print(行)...等待输出...虽然输出可能需要一些时间才能出现,但最后您肯定会看到包含IBM数据的行。练习6.9:创建一个复杂的管道通过执行更多的操作将管道的概念更进一步。>>>fromfollowimportfollow>>>importcsv>>>lines=follow('Data/stocklog.csv')>>>rows=csv.reader(lines)>>>forrowinrows:print(row)行数['BA','98.35','6/11/2007','09:41.07','0.16','98.25','98.35','98.31','158148']['AA','39.63','6/11/2007','09:41.07','-0.03','39.67','39.63','39.31','270224']['XOM','82.45','6/11/2007','09:41.07','-0.23','82.68','82.64','82.41','748062']['PG','62.95','6/11/2007','09:41.08','-0.12','62.80','62.97','62.61','454327']...这很有趣。您可以在这里看到follow()函数的输出被传递给csv.reader()函数,并且,我们现在得到一系列拆分行。练习6.10:创建更多管道组件让我们将这个想法扩展到更大的管道。首先,创建一个ticker.py文件,然后在ticker.py文件中创建一个函数来读取CSV文件,如上:#ticker.pyfromfollowimportfollowimportcsvdefparse_stock_data(lines):rows=csv.reader(lines)returnrowsif__name__=='__main__':lines=follow('Data/stocklog.csv')rows=parse_stock_data(lines)forrowinrows:print(row)接下来,创建一个选择特定列的新函数:#ticker.py...defselect_columns(rows,indices):forrowinrows:yield[row[index]forindexinindices]...defparse_stock_data(lines):rows=csv.reader(lines)rows=select_columns(rows,[0,1,4])returnrows再次运行程序,你应该看到输出按比例缩小为:['BA','98.35','0.16']['AA','39.63','-0.03']['XOM','82.45','-0.23']['PG','62.95','-0.12']...接下来,创建一个生成器函数来转换数据类型并构建字典。示例:#ticker.py...defconvert_types(rows,types):forrowinrows:yield[func(val)forfunc,valinzip(types,row)]defmake_dicts(rows,headers):forrow在行中:yielddict(zip(headers,row))...defparse_stock_data(lines):rows=csv.reader(lines)rows=select_columns(rows,[0,1,4])rows=convert_types(rows,[str,float,float])rows=make_dicts(rows,['name','price','change'])returnrows...再次运行程序,你应该能够看到像这样的字典流:{'name':'BA','price':98.35,'change':0.16}{'name':'AA','price':39.63,'change':-0.03}{'name':'XOM','price':82.45,'change':-0.23}{'name':'PG','price':62.95,'change':-0.12}...练习6.11:过滤数据创建一个函数来过滤数据。示例:#ticker.py...deffilter_symbols(rows,names):forrowinrows:ifrow['name']innames:yieldrow使用此函数过滤掉投资组合中的股票:importreportportfolio=report。read_portfolio('Data/portfolio.csv')rows=parse_stock_data(follow('Data/stocklog.csv'))rows=filter_symbols(rows,portfolio)forrowinrows:print(row)练习6.12:将所有代码放在一起请在ticker.py文件中编写函数ticker(portfile,logfile,fmt),它根据给定的投资组合、日志文件和表格格式创建实时股票代码。示例:>>>fromtickerimportticker>>>ticker('Data/portfolio.csv','Data/stocklog.csv','txt')NamePriceChange-----------------------------GE37.14-0.18MSFT29.96-0.09CAT78.03-0.49AA39.34-0.32...>>>ticker('Data/portfolio.csv','Data/stocklog.csv','csv')Name,Price,ChangeIBM,102.79,-0.28CAT,78.04,-0.48AA,39.35,-0.31CAT,78.05,-0.47...生成器函数并将它们链接在一起执行涉及数据流的流水线处理。或者,您可以创建一个将一系列管道阶段打包到单个函数调用中的函数(例如parse_stock_data()函数)。目录|上一节(6.2自定义迭代)|下一节(6.4生成器表达式)注:完整翻译见https://github.com/codists/practical-python-zh
