Python小白学习之路(二十三)—【生成器补充】
生成器的一些补充
接着下鸡蛋和吃包子!
补充一:生成器只能遍历一次
(总是把生成器比喻成母鸡下鸡蛋,需要一个下一个,首先是下出来的鸡蛋不能塞回
母鸡肚子里,其次是一个母鸡一生只能下一定数量的鸡蛋,下完了就死掉了)
#通过程序来理解什么意思
#程序一: def test():
for i in range(2):
yield i
t = test()
for i in t:
print(i)
t1 =(i for i in t)
print(list(t1)) #执行结果
0
1
[]
#程序分析
#1.程序开始执行以后,因为test函数中有yield关键字,所以test函数并不会真的执行,而是先得到一个生成器t.
#2.for循环遍历生成器t,并打印遍历结果0和1
#3.继续利用for循环遍历生成器t,因为该生成器已经遍历过一次,所有值已经取完,所以这次遍历不会取到任何值,则打印遍历结果为空列表
#程序二:
#实现功能:人口普查,
#功能一:统计 “人口统计” 文件中所有省份的总人数
#功能二:并计算出每一省份人数占总人数的百分比
#人口普查.text文件内容
{'name': '北京', 'population': 100}
{'name': '天津', 'population': 999}
{'name': '南京', 'population': 750}
{'name': '上海', 'population': 870} #程序:
def get_population():
with open('人口普查', 'r', encoding = 'utf-8') as f:
for i in f:
yield i
g = get_population()
all_population=sum(eval(i)['population'] for i in g)
print(all_population)
for i in g:
single_population = eval(i)['population']
print( single_population / all_population)
#程序分析:
#1.程序开始执行以后,因为get_population函数中有yield关键字,所以get_population函数并不会真的执行,而是先得到一个生成器g.
#2.all_population=sum(eval(i)['population'] for i in g) 总人数的获取
#对这段代码进行翻译一下
#第一步:通过for循环进行遍历生成器 g,其实就是执行 get_population 函数,打开txet文件,读取每一行内容
#第二步:每一行的内容读出来为字符串类型,通过eval()将字符串转换成字典类型,通过索引进行对每个省人口进行取值
#第三步:通过sum函数,对所取的值进行求和,计算总人口数
#3.通过对生成器g进行遍历,取出每一个省份的人数,并打印百分比
#通过分析,上述程序可实现要求。可运行结果如下:
2719
#只计算出总人数。为什么没有执行第二次遍历?原因就在于计算总人口时已经对生成器g遍历了一次,将值全部取出第二次遍历时,生成器中并没有值,因此也不会取出每一个省份的人数,并打印百分比
#程序改进(遍历时保存取值即可) def get_population():
with open('人口普查', 'r', encoding = 'utf-8') as f:
for i in f:
yield i
g = get_population()
s1 = eval(g.__next__())['population']
s2 = eval(g.__next__())['population']
s3 = eval(g.__next__())['population']
s4 = eval(g.__next__())['population']
s = [s1, s2 , s3, s4]
all_population = s1 + s2 + s3 + s4
for i in range(4):
print(s[i] / all_population) #执行结果
2719
0.036778227289444645
0.367414490621552
0.2758367046708349
0.3199705774181684
虽然功能实现了,可是我认为自己的程序写的实在太蹩脚了
因为没有什么基础,所以只能按照功能区一步一步写
希望之后有是有改进吧
大家对这个程序的实现有什么好的想法可以和我交流一下
补充二:生产消费者模型(本质是对 yield 一个应用)
#以吃包子的列子
#我们去包子铺买包子,肯定是去了店家边做边卖包子
#店家肯定不会让所有人等着,把需要的所有包子都做好,再卖给大家
#最高效率的就是我做一个人的,卖一个人的量
#现做现卖
#我们用程序来模拟这个过程
#吃包子进化理论(我自己胡乱起的名字)
#程序一:(只能实现一个人吃了一个包子) def producer_bun():
c1 = consumer('xhg')
c1.__next__()
c1.send('猪肉馅儿')
def consumer(name):
print('我是%s,我准备开始吃包子了'%name)
while True:
bun = yield
print('%s很开心的把%s吃掉了'%(name, bun))
producer_bun() #执行结果
我是xhg,我准备开始吃包子了
xhg很开心的把猪肉馅儿吃掉了
#程序二:(只能实现一个人吃了多个包子)
def producer_bun():
c1 = consumer('xhg')
c1.__next__()
for i in range(3):
c1.send('包子%s'%i)
def consumer(name):
print('我是%s,我准备开始吃包子了'%name)
while True:
bun = yield
print('%s很开心的把%s吃掉了'%(name, bun))
producer_bun() #执行结果
我是xhg,我准备开始吃包子了
xhg很开心的把包子0吃掉了
xhg很开心的把包子1吃掉了
xhg很开心的把包子2吃掉了
#最终版完美吃包子程序
def producer_bun():
c1 = consumer('xhg1')
c2 = consumer('xhg2')
c1.__next__()
c2.__next__()
for i in range(3):
c1.send('包子%s'%i)
c2.send('包子%s' % i)
def consumer(name):
print('我是%s,我准备开始吃包子了'%name)
while True:
bun = yield
print('%s很开心的把%s吃掉了'%(name, bun))
producer_bun()
设置断点,可以清楚的帮我们分析程序的执行过程。以此来充分理解yield的作用。

数字代表程序执行步骤
通过yield实现两个函数之间的切换
其中send函数作用同next函数
send()的两个功能:1.传值;2.next()。
Python小白学习之路(二十三)—【生成器补充】的更多相关文章
- Python小白学习之路(十三)—【递归调用】
一.递归调用定义 在函数内部,可以调用其他函数. 如果在调用一个函数的过程中直接或间接调用自身本身,则称为递归调用 从某种意义上来说,递归调用可以实现无限循环 二.递归调用的特性 必须有一个明确的结束 ...
- Python小白学习之路(二十二)—【生成器】
一.什么是生成器? 生成器可以理解成是一种数据类型,特殊地是生成器可以自动实现迭代器协议其他的数据类型需要调用自己内置的__iter__方法所以换种说法,生成器就是可迭代对象 !回忆:很重要的迭代器协 ...
- Python小白学习之路(二)—【Pycharm安装与配置】【创建项目】【运算符】【数据类型】
写在前面: 第二天的学习,感觉比昨天学习相对轻松一些,但是对于我这个编程语言功底很弱的人来说,还是稍稍微有些.....哈尔滨的天气一天天冷了下来,还飘着小雨,不过还是挺有意境的.充实而又忙碌的生活,让 ...
- Python小白学习之路(二十)—【打开文件的模式二】【文件的其他操作】
打开文件的模式(二) 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码.图片文件的jgp格 ...
- Python小白学习之路(二十六)—【if __name__ =='__main__':】【用状态标识操作】
规则一: 一个python文件中,只写一些可以运行的功能测试代码写在这句代码下面 if __name__ =='__main__': 在讲这边的时候,我不是很懂参考了一篇博客,地址如下:http:// ...
- Python小白学习之路(二十四)—【装饰器】
装饰器 一.装饰器的本质 装饰器的本质就是函数,功能就是为其他函数添加附加功能. 利用装饰器给其他函数添加附加功能时的原则: 1.不能修改被修饰函数的源代码 2.不能修改被修饰函数的调用 ...
- Python小白学习之路(二十一)—【迭代器】
迭代器 1.迭代器协议 对象必须提供一个 next 方法,执行该方法要么返回迭代中的下一项,要么就引起一个Stoplteration异常,以终止迭代(只能往后走不能往前退) 2.可迭代对象 实现了迭代 ...
- Python小白学习之路(二十五)—【装饰器的应用】
通过一个任务来加深对装饰器的理解和应用 回顾:装饰器的框架 def timmer(func): def wrapper(): func() return wrapper 任务:给以下正在运行的程序加一 ...
- Python小白学习之路(十七)—【内置函数二】
序列操作类函数 all() 功能:判断可迭代对象的每个元素是否都为True值注意:If the iterable is empty, return True.(举例3) 回顾:None '' ...
随机推荐
- Oracle启动两个监听
接上篇:Oracle服务器修改IP后 Oracle服务器更换IP后,办公网络里面可以正常访问了,外地的同事,连了vpn 也可以访问,以为可以收工回家,突然又有同事过来说,机房的服务器ping不通新的i ...
- keras环境
Windows 7 python3.6 在安装 Keras 之前, 需要确认自己已经安装好了 Numpy 和 Scipy. 安装个anaconda3就可以搞定 因为 Keras 是基于 Tensorf ...
- Linux关机操作
正确的关机流程为:sync > shutdown > reboot > halt 关机指令为:shutdown ,你可以man shutdown 来看一下帮助文档. 例如你可以运行如 ...
- Amount of Degrees(数位dp)
题目链接:传送门 思路:考虑二进制数字的情况,可以写成一个二叉树的形式,然后考虑区间[i……j]中满足的个数=[0……j]-[0……i-1]. 所以统计树高为i,中有j个1的数的个数. 对于一个二进制 ...
- springboot 容器启动事件
在springboot 容器启动时,我们需要在启动过程中做一些操作,比如启动容器后,执行某些代码. spring 提供了监听器,我们可以方便的实现这些操作. 在容器启动开始时: package com ...
- 学以致用十六-----Centos7.2编译安装mysql5.6.22
一.系统环境 二.卸载系统自带的mariadb rpm -qa | grep db rpm -e --nodeps mariadb-libs-5.5.60 rpm -e --nodeps mariad ...
- redis-server进程CPU百分百问题
结论:待确认是否为redis的BUG,原因是进程实际占用的内存远小于配置的最大内存,所以不会是内存不够需要淘汰.CPU百分百redis-server进程集群状态:slave临时解决办法:使用gdb将d ...
- C#-VS支持的语言
其中C语言选C++
- 大道至简第一章和java理论学时第一节。感受。
这周上了本学期的第一节java课程.课件上说了一些学习java的基本思想.举了个“愚公移山”的例子.这可能就像刚接触一门新的语言,来练习输出“HelloWorld”一样,已成惯例. “愚公移山”的这个 ...
- 【repost】 原生JS执行环境与作用域深入理解
首先,我们要知道执行环境和作用域是两个完全不同的概念. 函数的每次调用都有与之紧密相关的作用域和执行环境.从根本上来说,作用域是基于函数的,而执行环境是基于对象的(例如:全局执行环境即window对象 ...