python—迭代器、生成器
1、迭代器(iteration)
迭代器协议:提供next()方法,该方法要么返回迭代的下一项,要么异常。(只能往后走)
可迭代对象:实现迭代器协议的对象。
**字符串、列表、元祖、字典、集合、文件都不是可迭代对象,但在for循环中使用_iter_方法,可以变成可迭代对象。
**for循环可调用可迭代对象的_next_方法取值,且会捕捉异常
x = 'hello' ## 生成迭代器对象 iter_test = x.__iter__() print(iter_test) ## <str_iterator object at 0x00419FB0> ## next()去列表的值,取不到以后,会报异常 print(iter_test.__next__()) ## h print(iter_test.__next__()) ## e ## for for i in x: print(i)
x = ['aaa','bbb','ccc'] ## 生成迭代器对象 iter_test = x.__iter__() ## next()方法就是调用_next_()方法 print(next(iter_test))
2、生成器(generator)
一种数据类型,是可迭代对象
## 三元表达式 name = 'Amy' res='yes' if name =='Amy' else 'no' print(res) ## 如果true,返回yes,否则返回no
## 列表解析 li = [] for i in range(10): li.append('嘟嘟%s'%i) print(li) print(['嘟嘟%s'%i for i in range(10)]) print(['嘟嘟%s'%i for i in range(10) if i > 5 ])
(1)、生成器函数
yield返回结果,而不是return
## 生成器函数,可以返回多次 def test(): yield 1 yield 2 t = test() print(t) ## <generator object test at 0x005D0EB0> print(t.__next__()) ## 1 print(t.__next__()) ## 2
(2)、生成器表达式
把列表解析的[ ] 变成 ()
## 生成器表达式 s = ('嘟嘟%s'%i for i in range(10)) print(s) ## <generator object <genexpr> at 0x00400E70> print(s.__next__()) ## 嘟嘟0 print(next(s)) ## 嘟嘟1
def eggs(): li = [] for i in range(100): li.append('egg%s' %i) return li print(eggs()) ## 缺点:占空间大;效率低 ## 生成器 改进 def eggs(): for i in range(100): yield 'egg%s' %i s = eggs() print(next(s)) print(next(s))
生成器优点:
1、延迟计算,一次返回一个结果,不会一次生成所有结果,对于大数据处理非常有用;
— 列表解析:内存占用大,机器容易卡死
— 声称其表达式:几乎不占内存
2、提高代码可读性
## a.txt 内容 ## {'name':'北京','population':13} ## {'name':'福建','population':1645} ## {'name':'安徽','population':642} ## {'name':'河南','population':146} ## {'name':'河北','population':435} def get_population(): ret = [] with open('a.txt','r',encoding='utf-8') as f: for i in f: yield i p = get_population() print(eval(next(p))['name']) print('总人口:',sum(eval(i)['population'] for i in p))
3、生产者消费者模型
send() 方法
# yield 3 — 相当于return 函数的返回值 # x = yield — 接收send传过来的值,赋值给yield def test(): print('开始') first = yield 1 ## return 1 first=None print('第一次',first) yield 2 print('第二次') t = test() print(next(t)) ## 执行到 first = yield 1 # 开始 # 1 print(t.send(None)) ## 把None传给first,在执行到 yield 2 # 第一次 None # 2
## 生产者消费者模型 import time def producer(): ret = [] for i in range(10): time.sleep(0.1) ret.append('产品%s' %i) return ret def consumer(res): for index,product in enumerate(res): print('第%s个顾客,购买%s' %(index,product)) res = producer() consumer(res) ### 并发 def consumer(name): print('我是【%s】,要购买产品' %name) while True: product = yield print ('%s 购买了【%s】' %(name,product)) def producer(): c1 = consumer('Amy') next(c1) for i in range(10): c1.send('产品%s' %i) producer()