关于Python中yield的一些个人见解

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

 i (
    (( i*2 i  yield_test(5(i,)

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

最近在scrapy爬虫方面接触了很多yield,找了很多网上的资料,很多大神都给出了很透彻的理解方法。但是由于我是菜鸟一个,对于一些很专业的解释看得似懂非懂。于是乎找了一段代码,自己在pycharm中一步步调试,终于弄懂了yield的工作原理。

样例代码中定义了两个方法yield_test以及call,将会在接下来的迭代中调用。

首先,我们将一个参数“5”传进yield_test方法中,代码将会执行到以下步骤。

for i in range(n):

代码将会生产一个[0,1,2,3,4]的列表,将会在该列表中进行迭代,此时i=0,开始进行迭代

代码运行到

yield call(i)

时,将会将i=0传入到 call()方法中,返回一个运算结果"0"

接下来生成器yield将会执行一个类似return的操作,将i=0返回到

for i in yield_test(5):    print(i,",")

中,此时将会执行 print(i,",")语句,在Console窗口输出

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

完成以上的结果输出之后,由于yield的机制,下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行

此时代码将会返回到以下语句中继续迭代

print("i=",i)

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

Console窗口将会继续打印出第二条结果

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

执行完毕之后,将会继续在yield_test方法中进行第二次迭代

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

此时i的值将会由0变为1   PS:前面生成的列表就是[0,1,2,3,4],刚开始是0,下一次迭代就是1啦

yield将会重复进行迭代,将1传到call()方法,计算完成后返回到主循环里面继续输出  print(i,",")  然后在根据yield的特性返回到  print("i=",i)  输出到Console窗口中,以此类推。

 

总结,引用其他大神总结,yield的特性如下:

  1. 通常的for...in...循环中,in后面是一个数组,这个数组就是一个可迭代对象,类似的还有链表,字符串,文件。它可以是mylist = [1, 2, 3],也可以是mylist = [x*x for x in range(3)]。
    它的缺陷是所有数据都在内存中,如果有海量数据的话将会非常耗内存。

  2. 生成器是可以迭代的,但只可以读取它一次。因为用的时候才生成。比如 mygenerator = (x*x for x in range(3)),注意这里用到了(),它就不是数组,而上面的例子是[]。

  3. 我理解的生成器(generator)能够迭代的关键是它有一个next()方法,工作原理就是通过重复调用next()方法,直到捕获一个异常。可以用上面的mygenerator测试。

  4. 带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代,工作原理同上。

  5. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码开始执行。

  6. 简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后开始。

  7. 带有yield的函数不仅仅只用于for循环中,而且可用于某个函数的参数,只要这个函数的参数允许迭代参数。比如array.extend函数,它的原型是array.extend(iterable)。

  8. send(msg)与next()的区别在于send可以传递参数给yield表达式,这时传递的参数会作为yield表达式的值,而yield的参数是返回给调用者的值。——换句话说,就是send可以强行修改上一个yield表达式值。比如函数中有一个yield赋值,a = yield 5,第一次迭代到这里会返回5,a还没有赋值。第二次迭代时,使用.send(10),那么,就是强行修改yield 5表达式的值为10,本来是5的,那么a=10

  9. send(msg)与next()都有返回值,它们的返回值是当前迭代遇到yield时,yield后面表达式的值,其实就是当前迭代中yield后面的参数。

  10. 第一次调用时必须先next()或send(None),否则会报错,send后之所以为None是因为这时候没有上一个yield(根据第8条)。可以认为,next()等同于send(None)。

 

以上是个人对yield的一些个人简介,如有表达错误,希望指正。

其实很多看起来很难的东西,把它抄过来,然后在调试模式中一步一步地去观察代码的运行情况,观察变量的变化,这样对理解一样新事物会有很大的帮助(很显然是废话 = =!)

 

标签: yield

好文要顶 关注我 收藏该文 photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训 photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

photoshop培训,电脑培训,电脑维修培训,移动软件开发培训,网站设计培训,网站建设培训

Esing_Tse
关注 - 0
粉丝 - 0

+加关注

0

0

上一篇:在阿里云下搭建服务器时所遇到的问题

posted @ 2017-06-14 23:40 Esing_Tse 阅读(183) 评论(1编辑 收藏


评论

  

#1楼 2017-06-15 10:38 | 小函子  

MicroPython开发板:TPYBoard V702来电显示功能
一、什么是TPYBoard V702 
TPYBoard V702是山东萝卜电子科技有限公司最新开发的,目前市面上唯一支持通信通信功能的MicroPython开发板:支持Python3.0及以上版本直接运行。支持GPS+北斗双模通信、GPRS通信、短信功能、电话功能;板载温湿度、光敏、三轴加速度传感器、蜂鸣器、LCD5110显示屏。免费提供通信测试服务台实物如下图: 

二、利用TPYBoard V702完成接收提示来电,并在显示屏上显示来电号码及来电人员称谓 
1、具体要求 
利用TPYBoard V702完成接收提示来电,并在显示屏上显示来电号码及来电人员称谓
2、所需器件 
TPYBoard V702开发板 一块 
5110显示屏 一块 
Gsm手机卡 一张 
TPYBoard V702开发板板载GSM通信功能,无需外接 
3、板载通信功能及使用介绍 
V702的开发板的整体整体亮点置一就是能板载通信功能,只要在开发板的卡槽上插上一张可以使用的手机卡(不支持电信),即可使用该功能。 
开发板板载的通信功能包括了电话,短信,GPRS等功能,在这个实验里面我们只使用电话这个功能。 
开发板板载的通信功能已经设计的很完善,在接到来电的时候,会主动的把来电的信息通过串口4发送进来,这样一来作为用户的我们就是需要把数据进行相应的处理加显示就可以了。 
三、制作主要过程 
先上个图,下面再开始说代码的问题。 

这次不光有照片,还有视频:
链接内容
1、制作过程 
(1)首选我们需要做的是把5100显示屏插到702开发板的5110显示屏接口处; 
(2)在上面工作完成后,我们这里需要用到主要的类库,5110的类库,我们需要把这个类库的.py文件拷贝到开发板的盘符中; 
(3)完成以上工作后,我们开始main().py文件代码的编辑; 
(4)对需要用到的类库进行声明和定义; 
(5)把我们需要使用的变量进行一下定义; 
(6)把我们需要用到的接口进行声明和定义,这里我们主要用到了spi 1和串口4这两个接口,声明串口4的时候,需要把串口波特率设置为115200; 
(7)下面开始主函数的编写,这个实验里面我们用到了显示,我们在程序的开始部分先进行显示部分的初始化; 
(8)完成显示部分初始化之后,我们需要做一个最重要的事情,那就是定义“Y6”引脚为输出,然后把:“Y6”引脚拉低两秒以上,之后把此引脚拉高。因为“Y6”引脚是控制整个板载通信系统开启的开关,如果平时我们没有用到通信系统的话,为了节省功耗,板载通信系统是处于关闭状态的,需要使用时只需要拉低“Y6”引脚两秒以上; 
(9)当看到开发板上的红色直插LED灯快速闪烁的时候,说明板载通信系统正在启动,当这个红色直插指示灯结束快闪(如果插在开发板卡槽上的手机可用,指示灯处于慢闪状态)说明板载通信系统已经启动; 
(10)完成以上工作后,准备工作就已经完成了,剩下需要做的就是监控串口4是否有数据发送过来,当检测到串口4有数据发送过来,对数据进行相应的判断及处理,并显示到显示屏上即可。 
2、具体代码:
import pyb
import upcd8544
from machine import SPI,Pin
from pyb import UART
from ubinascii import hexlify
from ubinascii import *#以上内容为声明所使用的类库


leds = [pyb.LED(i) for i in range(1,5)]
P,L,SHUCHU=0,0,0
SPI = pyb.SPI(1) #DIN=>X8-MOSI/CLK=>X6-SCK
#DIN =>SPI(1).MOSI 'X8' data flow (Master out, Slave in)
#CLK =>SPI(1).SCK 'X6' SPI clock
RST = pyb.Pin('X20')
CE = pyb.Pin('X19')
DC = pyb.Pin('X18')
LIGHT = pyb.Pin('X17')
lcd_5110 = upcd8544.PCD8544(SPI, RST, CE, DC, LIGHT)#以上内容为声明并初始化显示屏
count_=0
N2 = Pin('Y3', Pin.OUT_PP)#定义“Y3”为输出模式,这个引脚是控制蜂鸣器的,来电话了 #需要响铃的
N1 = Pin('Y6', Pin.OUT_PP)#定义“Y6”位输出模式,“Y6”引脚是板载通信系统的开关控 #制引脚
N1.low()
pyb.delay(2000)
N1.high()
pyb.delay(10000)#通过拉低拉高开光控制引脚,启动通信系统
u2 = UART(4, 115200)#设置串口4,并设置串口波特率为115200
i='0'
w=0
d=0
q=0
G=0
j=0
while 0<1:
N2.low()#设置蜂鸣器控制引脚为低电平,不让蜂鸣器响
if(u2.any()>0):#检测串口4是否有数据,如果有数据执行以下
_dataRead=u2.readall()
if _dataRead!=None:#判断串口4的数据是否为空,不为空执行以下代码
print('原始数据=',_dataRead)
print('原始数据长度:',len(_dataRead))
print('123',_dataRead[2:6])
RING=_dataRead[2:6]#截取包头,这个包头是为了判断数据是否正确的重要依 #据
print('111',_dataRead[18:29])
HM=_dataRead[18:29]#数据的18至29位是数据中携带的手机号码,我们把它 #们保存出来
WD='No such person'#设置一个变量,这个变量我们可以称为是电话本类比变 #量,主要是作为显示时什么人来电,例如显示张三, #或者李四
if(RING==b'RING'):#判断包头正确,执行下面代码
if(HM==b'18654868920'):#判断来电是否是一个已经存储的号码
WD='TPYBoard_GPS'#如果是,显示存储名称,如果没有存储显示'No #such person'
#**********************时间************************
N2.high()#拉高蜂鸣器控制引脚,使蜂鸣器响铃
lcd_5110.lcd_write_string('Phone Number:',0,0)
lcd_5110.lcd_write_string(HM.decode("utf8"),2,1)
lcd_5110.lcd_write_string('The contact:',0,2)
lcd_5110.lcd_write_string(str(WD),0,3)#显示相应的来电号码,来电人称谓 #等
pyb.delay(1000)

http://www.cnblogs.com/esing-tse/p/7011595.html

网友评论