简洁的列表解析形式 ----[ i for i in range(10) ]
生成器表达式 ----[ i for i in range(10) ]
自己的问题:
return和yield可以连用吗? 不能,会报错。
def test(): yield 1 yield 2 yield 3 res = test() print(res) #这样是打印生成器,不是yield返回值 print(res.__next__()) #这样才是打印yield返回值,调用next的方法 结果 <generator object test at 0x0000021CD6E99728> 1
next----触发----yield
yield:
1.返回值
2.保留函数运行状态,基于从上次yield的结束末尾开始
消费者和生产者模型
# 生产包子(100个) 第一种方法 def product_baozi1(): ret = [] for i in range(100): ret.append(‘包子%s‘%i) return ret baozi_list = product_baozi1() print(baozi_list) 第二种方法 def product_baozi2(): for i in range(100): print(‘正在生成包子‘) #要一次用一次,有一个值就可以马上处理 yield ‘一屉包子%s‘%i print(‘开始买包子‘) pro_g = product_baozi2() baozi_1 = pro_g.__next__() print(baozi_1) baozi_2 = pro_g.__next__() print(baozi_2) baozi_3= pro_g.__next__() print(baozi_3) 结果 [‘包子0‘, ‘包子1‘, ‘包子2‘, ‘包子3‘, ‘包子4‘, ‘包子5‘, ‘包子6‘, ‘包子7‘, ‘包子8‘, ‘包子9‘, ‘包子10‘, ‘包子11‘, ‘包子12‘, ‘包子13‘, ‘包子14‘, ‘包子15‘, ‘包子16‘, ‘包子17‘, ‘包子18‘, ‘包子19‘, ‘包子20‘, ‘包子21‘, ‘包子22‘, ‘包子23‘, ‘包子24‘, ‘包子25‘, ‘包子26‘, ‘包子27‘, ‘包子28‘, ‘包子29‘, ‘包子30‘, ‘包子31‘, ‘包子32‘, ‘包子33‘, ‘包子34‘, ‘包子35‘, ‘包子36‘, ‘包子37‘, ‘包子38‘, ‘包子39‘, ‘包子40‘, ‘包子41‘, ‘包子42‘, ‘包子43‘, ‘包子44‘, ‘包子45‘, ‘包子46‘, ‘包子47‘, ‘包子48‘, ‘包子49‘, ‘包子50‘, ‘包子51‘, ‘包子52‘, ‘包子53‘, ‘包子54‘, ‘包子55‘, ‘包子56‘, ‘包子57‘, ‘包子58‘, ‘包子59‘, ‘包子60‘, ‘包子61‘, ‘包子62‘, ‘包子63‘, ‘包子64‘, ‘包子65‘, ‘包子66‘, ‘包子67‘, ‘包子68‘, ‘包子69‘, ‘包子70‘, ‘包子71‘, ‘包子72‘, ‘包子73‘, ‘包子74‘, ‘包子75‘, ‘包子76‘, ‘包子77‘, ‘包子78‘, ‘包子79‘, ‘包子80‘, ‘包子81‘, ‘包子82‘, ‘包子83‘, ‘包子84‘, ‘包子85‘, ‘包子86‘, ‘包子87‘, ‘包子88‘, ‘包子89‘, ‘包子90‘, ‘包子91‘, ‘包子92‘, ‘包子93‘, ‘包子94‘, ‘包子95‘, ‘包子96‘, ‘包子97‘, ‘包子98‘, ‘包子99‘] 正在生成包子 一屉包子0 开始买包子 正在生成包子 一屉包子1 开始买包子 正在生成包子 一屉包子2
母鸡下蛋传说
#母鸡下蛋传说 第一种方法 def xiadan(): ret = [] for i in range(100): ret.append(‘鸡蛋%s‘%i) return ret print(xiadan()) #缺点是占用空间大(内存)和效率低 第二种 def xiadan1(): for i in range(100): yield ‘鸡蛋%s‘%i laomuji = xiadan1() jidan = laomuji.__next__() print(‘海绵宝宝取了‘,jidan) jidan = laomuji.__next__() print(‘海绵宝宝取了‘,jidan) jidan = laomuji.__next__() print(‘海绵宝宝取了‘,jidan) 结果
第一种 [‘鸡蛋0‘, ‘鸡蛋1‘, ‘鸡蛋2‘, ‘鸡蛋3‘, ‘鸡蛋4‘, ‘鸡蛋5‘, ‘鸡蛋6‘, ‘鸡蛋7‘, ‘鸡蛋8‘, ‘鸡蛋9‘, ‘鸡蛋10‘, ‘鸡蛋11‘, ‘鸡蛋12‘, ‘鸡蛋13‘, ‘鸡蛋14‘, ‘鸡蛋15‘, ‘鸡蛋16‘, ‘鸡蛋17‘, ‘鸡蛋18‘, ‘鸡蛋19‘, ‘鸡蛋20‘, ‘鸡蛋21‘, ‘鸡蛋22‘, ‘鸡蛋23‘, ‘鸡蛋24‘, ‘鸡蛋25‘, ‘鸡蛋26‘, ‘鸡蛋27‘, ‘鸡蛋28‘, ‘鸡蛋29‘, ‘鸡蛋30‘, ‘鸡蛋31‘, ‘鸡蛋32‘, ‘鸡蛋33‘, ‘鸡蛋34‘, ‘鸡蛋35‘, ‘鸡蛋36‘, ‘鸡蛋37‘, ‘鸡蛋38‘, ‘鸡蛋39‘, ‘鸡蛋40‘, ‘鸡蛋41‘, ‘鸡蛋42‘, ‘鸡蛋43‘, ‘鸡蛋44‘, ‘鸡蛋45‘, ‘鸡蛋46‘, ‘鸡蛋47‘, ‘鸡蛋48‘, ‘鸡蛋49‘, ‘鸡蛋50‘, ‘鸡蛋51‘, ‘鸡蛋52‘, ‘鸡蛋53‘, ‘鸡蛋54‘, ‘鸡蛋55‘, ‘鸡蛋56‘, ‘鸡蛋57‘, ‘鸡蛋58‘, ‘鸡蛋59‘, ‘鸡蛋60‘, ‘鸡蛋61‘, ‘鸡蛋62‘, ‘鸡蛋63‘, ‘鸡蛋64‘, ‘鸡蛋65‘, ‘鸡蛋66‘, ‘鸡蛋67‘, ‘鸡蛋68‘, ‘鸡蛋69‘, ‘鸡蛋70‘, ‘鸡蛋71‘, ‘鸡蛋72‘, ‘鸡蛋73‘, ‘鸡蛋74‘, ‘鸡蛋75‘, ‘鸡蛋76‘, ‘鸡蛋77‘, ‘鸡蛋78‘, ‘鸡蛋79‘, ‘鸡蛋80‘, ‘鸡蛋81‘, ‘鸡蛋82‘, ‘鸡蛋83‘, ‘鸡蛋84‘, ‘鸡蛋85‘, ‘鸡蛋86‘, ‘鸡蛋87‘, ‘鸡蛋88‘, ‘鸡蛋89‘, ‘鸡蛋90‘, ‘鸡蛋91‘, ‘鸡蛋92‘, ‘鸡蛋93‘, ‘鸡蛋94‘, ‘鸡蛋95‘, ‘鸡蛋96‘, ‘鸡蛋97‘, ‘鸡蛋98‘, ‘鸡蛋99‘] 第二种 海绵宝宝取了 鸡蛋0 海绵宝宝取了 鸡蛋1 海绵宝宝取了 鸡蛋2
生成器总结:
函数用return
生成器用yield,可以保留状态
优点1.延迟计算,要的时候给你,也就是说,他不会一次性的生成所有的结果。这对于大数据处理,将会非常有用
列表解析
sum( [ i for i in range(10000000) ] ) 内存占用大,机器容易卡死
生成器表达式
sum( i for i in range(10000000)) 几乎不占内存
优点2.生成器有效提高代码可读性
人口普查
人口普查.txt {‘name‘:‘北京‘,‘population‘:10100} {‘name‘:‘南京‘,‘population‘:10200} {‘name‘:‘东京‘,‘population‘:10300}
def get_population():
with open(‘人口普查.txt‘, ‘r‘, encoding=‘utf-8‘) as f:
for i in f:
yield i
g1=get_population()
g=get_population() #将生成器赋值给g
# s1 = eval(g.__next__()) #用eval将字符结构提取出来进行运算,因为从文章截取为字符串类型
# print(s1[‘population‘]) #取人口数量
# print(g.__next__())
#总人口
# res = 0
# for p in g:
# p_dic = eval(p)
# print(p_dic[‘population‘])
# res += p_dic[‘population‘]
# print(res)
#总人口(另一种)
for p in g:
all_popu = sum(eval(p)[‘population‘]for p in g)
print(int(all_popu))
for i in g1:
print(int(eval(i)[‘population‘])/all_popu)
注意事项:将生成器赋值给g,如果前面迭代完了,后面g就不能再用,只能迭代一次
还有的是文件名称要写完全,和编码,什么编码写的就用什么编码解。
int和str不可以进行相除
生产者消费者模型
并发运行 就是同时运行——利用yield, 因为yield可以保留状态
python是顺序运行
补充
1.yield相当于return控制的是函数的返回值
2.x=yield 的另外一个特性,接收send传过来的值,赋值给x
def test(): print(‘开始了‘) firt = yield 1 #默认firt=None print(‘第一次‘,firt) yield 2 print(‘第二次‘) t = test() #这样没有运行 res = t.__next__() #这样才算执行 print(res) #生成器运行的方法有三种 1.t.__next__() 2.next(t) 3.t.send(None) 其中send有两个功能,一是可以触发生成器运行,接着运行。二是函数停留再firt那个位置,我就是给firt赋值的
单人的消费者模式
单线程并发,来回的切换
def consumer(name): print(‘我是[%s],我准备开始吃包子了‘%name) while True: baozi = yield print(‘%s很高兴把[%s]吃掉了‘%(name,baozi)) def producer(): c1 = consumer(‘wwe‘) c1.__next__() for i in range(10): c1.send(‘包子%s‘%i) producer()