生成器:就是自己用python代码写的迭代器,生成器的本质就是迭代器
l1 = [1, 2, 3] iter1 = iter(l1) print(iter1) #<list_iterator object at 0x00000247A62CDDD8>
用以下方式构建一个生成器:
1.通过生成器函数
2.生成器表达式
def func1(x): x += 1 print(111) print(222) print(333) yield x x += 2 print(666) yield 'ake' x += 3 yield 4 print(345) d = func1(5) #生成器函数的对象 # print(d) #<generator object func1 at 0x0000021EF9F5E938> 生成器函数的地址 print(d.__next__()) #111 222 333 6 print(d.__next__()) #666 ake 因为yield没有返回x += 2 的值,所以打印的没有x print(d.__next__()) #ake 4 print(d.__next__()) #打印出345,但是报错
一个next 对应一个yield ,yield 将值返回给生成器对象。__next__()
yield跟return的区别:
return 结束函数,并将值返回给函数的执行者
yield 不会结束函数,一个next 对应yield,给生成器对象.__next__()返回值
生成器函数 vs 迭代器
区别1:自定制的区别
l1 = [1,2,3,4,5] l1.__iter__() #迭代器 def func1(x): #生成器 x += 1 yield x x += 2 yield x x += 3 yield 4 g1 = func1(5) print(g1.__next__()) #6 print(g1.__next__()) #8 print(g1.__next__()) #4
区别2:内存级别的区别
迭代器是需要可迭代对象进行转化,从本质就节省内存
生成器直接创建,不需要转化,从本质就节省内存
def func1(): for i in range(1,10000): yield i g1 = func1() for i in range(50): print(g1.__next__()) #打印的是1-50 for i in range(50): print(g1.__next__()) #打印的是51-100
每循环五十个,就打印五十个,非常节省内存
send 与 next 的区别:
def func1(): count = yield 6 print(count) count1 = yield 7 print(count1) yield 8 g = func1() #next(g) #g.send('ake') #next(g) print(next(g)) #这个next执行第一个yield 6 print(g.send('ake')) #send把值传给上一个yield,count = ‘ake’ 然后执行yield 7,count没有值,所以是None print(next(g)) #这个next执行的是yield 8
send 与 next一样,也是对生成器取值(执行一个yield)方法
send 可以给上一个yield传值
第一个取值永远都是nex
最后一个yield永远也得不到send传的值
列表推导式:一行代码几乎搞定你需要的任何列表
循环模式
l =[i for i in range(1,20) ] print(l)
筛选模式
l3 = [i for i in range(1,15) if i % 3 == 0] print(l3)
列表推导式优点:一行解决,方便
缺点:不易排错,不能超过三次循环
列表推导式不能解决所有列表的问题,所以不要太刻意用
生成器表达式:只需要将列表推导式[] 换成()
g = (i for i in range(50)) print(g.__next__()) #0 print(g.__next__()) #1 print(g.__next__()) #2
一个next 打印一个