Python基础教程批量任务处理神器

Python中有一个特别晦涩难懂的概念,就是生成器和yield。特别地,如果我们使用scrapy框架进行爬虫开发,就避不开yield这个关键词,所以,我们需要知道yield是什么。我们今天不解释概念,直接用下面的图说话:

这样是最容易理解的

其实这东西的概念就是一句话:定义一个函数,函数中有yield,就是生成器,没有yield,就是普通函数。

1、yield初步接触

yield所在的函数(也就是生成器)它的行为和普通函数是不一样的,我们看下面的这段代码和它的输出:

自己写了一个生成器

大家看,如果我是一个寻常的p这个函数,它正常打印数字,当我使用yield的时候,它就不会执行函数了,它不打印,而是返回一个generator对象。

2、yield有什么用

我们只需要牢记一点:生成器返回的对象只有调用它的__next__()方法的时候才会执行,而且它是可迭代的。

先看第一点,调用__next__()方法才会执行:

迭代器

第9行输出一个迭代器对象,第10行输出了具体的数字。

究极之问:这东西这么设计到底有什么用?我们从需求入手:

1、现在我要生成10个随机数,这个在Python中也很简单:

生成10个随机数

2、现在我要生成1万个随机数。这很简单,把代码第5行的10改成就好了。但是问题是:对于服务器程序来说,如果每次请求进来都要创建一个长度为的列表存储数字,内存和CPU开销都太大了,我们把它改成这样:

使用生成器生成10个随机数

划重点:第12行代码执行时并不会立即生成10个数,而是会在第13行的for循环执行的时候再生成。不信?我们改一下看它的结果:

注意第13行

第13行的输出都出来了,再碰到for循环的时候才会有数据。

归纳总结一下:生成器执行时,遇到yield会出让CPU,完成生成器的创建,但是只有真正对它进行迭代的时候,才执行具体的操作。scrapy这个爬虫框架里就是这么设计的,它的逻辑就是:我使用生成器的方式先创建个任务,先不执行,等到需要执行的时候直接从生成器启动。

真的已经很简单了

4、写在最后

生成器的__next__()方法当我们使用for循环遍历它时,会自动调用,当然,也可以手动调用。

手动调用生成器的__next__()

大家看输出流程,第一次调用have()的__next__(),输出before之后就回来得到True,并不会执行after,第二次调用have()的__next__()的时候,去执行after,然后准备下一次迭代,因为没有代码了,不能进行下一次迭代了,所以抛出异常。

生成器其实确实是一个神器,我们以后如果涉及到并发编程,涉及到爬虫,还会再碰到它,但是我相信通过本文的学习,大家都已经掌握了。




转载请注明:http://www.aierlanlan.com/rzdk/2851.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了