yield的基本使用

yield一般多用于生成器的创建,通过next()和send方法进行调用。

def demo01():print('start! 第1次循环')for i in range(10):c = yield iprint('c ---->',c,'\n')print('!!!!end!!!! 第%d次循环'%(i+1))if __name__ == '__main__':d = demo01()print('=========')print('第一次打印返回值:',next(d))print('=========')print('第二次打印返回值:',d.send(11))print('=========')print('第3次打印返回值:',next(d))

结果:

=========
!!!!start!!!! 第1次循环
第一次打印返回值: 0
=========
c ----> 11
!!!!end!!!! 第1次循环
第二次打印返回值: 1
=========
c ----> None
!!!!end!!!! 第2次循环
第3次打印返回值: 2

如果把yield看作是一个return,那么执行到yield的时候就是返回指定的数据,然后跳出函数。

  • 此时 d 就是一个生成器,由于函数没有被执行过,执行第一个next时,函数正式被运行,做第一步的print输出,然后进入for循环,遇到yield后返回指定 i 值并跳出函数执行,此时 i =0,所以第一次打印的返回值为0
  • 第二步使用了send()函数,此时从赋值的那一步开始执行(即通过yield跳出的那一步)并将传入的值赋值给了c,此时c = 11,然后继续向下执行,结束第一次循环,再次循环遇到yield时,返回的 i 值为1。
  • 第三步再次使用了next方法,依旧从跳出的那一步开始向下执行,结束第2次循环,再次遇到yield时,返回 i 值,此时 i = 2。
    • 但是,在结束第2次循环之前,在打印c的时候显示c = None。这是因为在第二步使用send函数跳出后,c并没有被赋值,在执行左边的yield时,就已经跳出了所以并没有执行复制的操作,所以这是默认赋值为None,所以在进行第三步时,c为None。

综上所述可以看出,两种调用方法,都是从上一步结束的地方继续执行,next()不会传入参数,而send可以向函数内传入参数,通过yield的位置传参。

def demo02():for i in range(10):c = yield iprint('c1 ---->',c)def demo03():for i in range(10):yield ic = i print('c2 ----->',c)d2 = demo02()
d3 = demo03()
next(d2)
next(d3)
d2.send(11)
d3.send(11)===结果===
c1 ----> 11
c2 -----> 0

demo03中虽然依旧使用了send传参,但是继续执行上一步终止处的程序后,新传入的参数并没有被赋值,因此传入的参数无效。

常见yield的异常

TypeError: can't send non-None value to a just-started generator
第一次调用生成器时,只能用send(None)或next()方法,不要直接send赋值,不然会报这个错误。
官方文档里详细解释了这个异常。是因为当生成器创建,从顶部开始执行函数时,并没有可以接收yield值的表达式,所以不可以使用带有非None参数的send(),必须提前调用一次send(None)或next()方法。

官方说明如下:

Because generator-iterators begin execution at the top of the
generator’s function body, there is no yield expression to receive a value when the generator has just been created. Therefore, calling send() with a non-None argument is prohibited when the generator iterator has just started, and a TypeError is raised if this occurs (presumably due to a logic error of some kind). Thus, before you can communicate with a coroutine you must first call next() or send(None) to advance its execution to the first yield

StopIteration
每一次调用next()方法后都会执行到yield位置结束,然后返回值,如果程序已经执行到最低端无法继续向下执行,此时仍然调用了方法,就会抛出这个异常。

在scrapy中关于yield的使用

在scrapy中,关于yield最常见的两个操作就是yield scrapy.Requestyield scrapy.item

scrapy.Request

def parse(self,response):···yield scrapy.Request(url=url,callback=self.detail_parse)

向response中获取的新链接再次发起请求,请求完成后调用指定回调函数。

scrapy.item

def detail_parse(self,response):item = DemoItem()····yield item

通过yield将获取的item传输到管道文件进行下一步处理。

在scrapy中使用yield时遇到的注意事项

如果在scrapy中定义了一个非回调函数,那么在这个函数中无法进行yield scrapy.Requestyield scrapy.item的操作,此时yield在这里起到的是它本身的基础作用,不是scrapy赋予它的作用,而使用了yield的非回调函数也只是一个普通的生成器。

yield的使用和在scrapy框架中的使用相关推荐

  1. scrapy框架中实现登录人人网(一)(最新登录方式)

    最近在弄scrapy框架的问题,感觉里面好玩的东西有很多,无意中在bilibili中看到关于在scrapy实现登录人人网的视频,人人网可能用户少,所以在现在的一些博客和教程里面看到最新的登录方法几乎没 ...

  2. 在scrapy框架中如何设置开放代理池达到反爬的目的

    我们在随机爬取某个网站的时候,比如对网站发出成千上万次的请求,如果每次访问的ip都是一样的,就很容易被服务器识别出你是一个爬虫.因此在发送请求多了之后我们就要设置ip代理池来随机更换我们的ip地址,使 ...

  3. Scrapy框架中的crawlspider爬虫

    1 crawlspider是什么 在spider中要寻找下一页的url地址或者内容的url地址,想想是否有简单的方法省略寻找url的过程? 思路: 从response中提取所有的满足规则的url地址 ...

  4. python pipeline框架_Python爬虫从入门到放弃(十六)之 Scrapy框架中Item Pipeline用法...

    原博文 2017-07-17 16:39 − 当Item 在Spider中被收集之后,就会被传递到Item Pipeline中进行处理 每个item pipeline组件是实现了简单的方法的pytho ...

  5. Python爬虫从入门到放弃(十五)之 Scrapy框架中Spiders用法

    Spider类定义了如何爬去某个网站,包括爬取的动作以及如何从网页内容中提取结构化的数据,总的来说spider就是定义爬取的动作以及分析某个网页 工作流程分析 以初始的URL初始化Request,并设 ...

  6. Scrapy框架中解决OSError=[Errno 2] No such file or directory: 'Xvfb': 'Xvfb'

    当在scrapy框架的Middlewares.py中导入以下语句后报错 from pyvirtualdisplay import Display display = Display(visible=0 ...

  7. Scrapy框架中管道的使用

    1. pipeline中常用的方法: 管道能够实现数据的清洗和保存,能够定义多个管道实现不同的功能,其中有个三个方法: process_item(self,item,spider):实现对item数据 ...

  8. python中scrapy的middleware是干嘛的_Python之爬虫(十九) Scrapy框架中Download Middleware用法...

    这篇文章中写了常用的下载中间件的用法和例子. Downloader Middleware处理的过程主要在调度器发送requests请求的时候以及网页将response结果返回给spiders的时候,所 ...

  9. Scrapy框架的学习(11.scrapy框架中的下载中间件的使用(DownloaderMiddlewares))

    1.Downloader Middlewares (下载中间键):引擎会先把Requets对象交给下载中间键再然后交给Downloader 2.使用方法: (1) 编写一个Downloader Mid ...

最新文章

  1. Apple首篇AI文章,SimGAN
  2. Week2 Teamework from Z.XML 软件分析与用户需求调查(四)Bing桌面及助手的现状与发展...
  3. 将C4C Service Request中的summary和其他附件同步到ERP的Billing Request去
  4. 如何在IE地址栏显示自己的小图标
  5. activiti-explorer 启动报错 Error creating bean with name 'demoDataConfiguration'
  6. 《机器学习实战》第二章学习笔记:K-近邻算法(代码详解)
  7. Cesium:在地球上加载Geoserver图层
  8. 数值分析实验四 最小二乘法曲线拟合
  9. 进qq空间显示服务器失败,QQ空间找不到服务器-进空间找不到服务器的解决办法...
  10. UE4数据库 Mysql
  11. 利用python爬取教务系统中成绩
  12. 【魔方攻略】镜面魔方教程(原创)
  13. 和异性合租是什么样的体验?
  14. 微信移动端数据库组件WCDB系列(二) — 数据库修复三板斧
  15. 2021年10个最美的边框效果,CSS实现,可以直接使用
  16. 华为交换机traffic策略设置
  17. 优维科技应用CMDB在招商基金的案例分享
  18. 26岁,2020 - 观周浩《书记》
  19. Deep Splitting and Merging for Table Structure Decomposition 中文翻译 (表格结构识别)
  20. 在容器中编译go项目出现cannot find packages的问题

热门文章

  1. FAT和NTFS文件系统的区别
  2. v42.05 鸿蒙内核源码分析(中断切换) | 系统因中断活力四射 | 百篇博客分析鸿蒙源码
  3. LeetCode--剑指 Offer 22. 链表中倒数第k个节点
  4. Windows 8操作系统让你网络生活产生革命的变化
  5. 手机网站优化该如何推广
  6. cef支持.net6.0
  7. Android Studio —— ArrayAdapter
  8. Hdp + Ambari 本地源安装
  9. 医惠科技完成重组上市,开启智慧医疗服务新篇章
  10. 架设单位内部FTP服务器