设为首页 收藏本站
查看: 1323|回复: 0

[经验分享] Python17 生成器

[复制链接]

尚未签到

发表于 2018-8-12 07:29:52 | 显示全部楼层 |阅读模式
1.列表生成式(推导式列表)
DSC0000.png

  通过for i in range(10)来循环0-9折10个数字,然后将每一个数字赋值给i,i在乘以2得出图中下面的结果。
  

a = []  for i in range(10):
  a.append(i*2)
  

  
print (a)
  

DSC0001.png

  结果是一样的
  

a = [i * 2for i in range(100)]  
print (a)
  

DSC0002.png

  列表生成式所生成的这些数据是会被放入到内存中的(除非删除或执行程序结束),可以随调用其中的任意数据。
  

print (a[10])  

DSC0003.png

  可以看到可以直接print (a10)来取值,能直接取值说明这个值是一直保存在内存中的,如果这个值元素的数量少到不会占很多资源,但是假如元素有一千万,一个亿时就会占用很多内存空间了。

2.生成器
  

c = (i * 2for i in range(100))  
print (c)
  

DSC0004.png

  可以看到,只是将中括号变成小括号后,输出的只是一个生成器,这个生成器当前没有任何的数据放在内存中,只有被调用的时候才会在内存中生成,结束后就删除内存中的元素,不调用的话就不会一直占用内存空间。
  

print (c[10])  

DSC0005.png

  可以看到使用print (c10)去引用内存中的数据并不存在,因为生成器没有被调用,所以没有任何数据元素存在内存中,所以这里会报错。
  

for i in c:  print (i)
  

DSC0006.png

  通过for来调用c,赋值给i,在打印i,这时候就可以看到一个个的数字被新生成
  print (c10)   #生成结束后我们在试着去引用c的元素,可以看到下图依然报错,这说明生成器被调用结束后,生成的元素值会在内存中删除,不会一直占用内存空间。
DSC0007.png

  

c = (i * 2for i in range(100))  
print (c.__next__())
  
print (c.__next__())
  
print (c.__next__())
  

DSC0008.png

  可以通过c.next()来不断的取c的下一个值,第一个值0,第二个2,以此类推来生成上一个值的下一个值。
  下面我们在pycharm的python console中测试,这样取值能更方便一些
DSC0009.png

DSC00010.png

  循环到50630后,这里使用了ctr+c强制停止了
DSC00011.png

  然后通过c.next()可以看到,可以继续在中断值的位置继续获取下面的值。
  当前已经生成了50634这个值,之前生成的值都已经没有了,被删除了,而且后面的值还没有生成,所以生成器只会记住当前的数字
DSC00012.png

DSC00013.png

DSC00014.png

  可以看到生成过的数字当前并不存在,说明已经被删除掉了,生成器只记住了当前的值。
  所以生成器并不会大量的去占用内存,同一时间只会存在一个值,所以有大量数据的时候,生成器是很常用的。
  在3.X版本中使用next(),在2.7中使用next()
  使用next()只能一个一个的去生成,所以一般都常使用for来循环生成。

3.函数定义生成器
  斐波那契数列:除了第一个和第二个数外,任意一个数都可以由前两个数相加得到:
DSC00015.png

  有规律,可以被推到出来的数字
DSC00016.png

  print (b)下面的 a,b = b,a+b  相当于 0,1 = 1,0+1,这里的a+b的a其实是引用了while上面的b,因为当前代码并没有执行完成所以a不会是1。
  前两位相加a+b=0+1,然后是1+1=2,  1+2=3,  2+3=5.....
DSC00017.png

  目前还不算是一个生成器
DSC00018.png

  可以看到将print改成yield 就算是一个生成器了,只有生成器可以使用 f.next()
DSC00019.png

  通过next调用一次,返回一个值
DSC00020.png

DSC00021.png

  可以看到for循环是继续3来之后来循环的。
  这里我们并没有看到return返回的done,因为for循环无法打印函数的返回值。
DSC00022.png

DSC00023.png

  不断使用next可以看到错误信息和其后面的done
  在斐波那契中我们可以大概定位有多少个数字,但是如果是在其他情况和场景下,我们不知道有多少个,且我们使用next超过了这些实际的个数就会报错,比如我们在调用函数时fib(10),只赋予了10个,但是我们使用next却超过了10个,这里就会报错。
DSC00024.png

  通过try一直print ('f:',x) 直到抓取到StopIteration 这个错误 将其设为别名e,然后执行该except下面的代码
DSC00025.png

  StopIteration这个错误信息就是相当于通过不断的print ('f:',x) 来发现的,这个本身就代表了 上一个代码中的StopIteration:done,只不过这里将其e作为别名,而e.value,只是StopIteration:done中的这个done,所以最后打印的是Generator return value: done。
DSC00026.png

  使用断点来查看步骤:
  从第5步,调用函数就会返回到生成器函数,在返回之前会保留该位置,一直到第8步会将b当前的值传给第9步的x(在传之前会保留yield这个位置,保留中断状态,下次返回继续),第9步打印x,因为还没有try完成,所以到了第10步,然后11步又返回生成器函数(返回的是上次保留的位置),因为是while循环所以到了第14步,第14步又到了15步,这样后续以此类推。
  yield的作用可以保留当前位置状态,将值返回出去
  生成器可以实现单线程中并发(协程),速度比多线程还要快。
DSC00027.png

  send与next相同,都是用来唤醒yield,只不过send还会传值
DSC00028.png

DSC00029.png

DSC00030.png

  异步

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-550356-1-1.html 上篇帖子: 27. Python对Mysql的操作(2) 下篇帖子: Python04 模块初识
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表