生成器,推导式

一.生成器:

生成器的实质就是迭代器

在python中有三种方式获取生成器:

1.通过生成器函数

2.通过各种推导式来实现生成器

3.通过数据的转换也可以获取生成器

二.通过生成器函数获取生成器:

def func():
    print('哈哈')
    yield '呵呵'   #有yield就是生成器
ret = func() #通过函数来创建一个生成器即生成器函数被执行,获取的是生成器,而不是函数的执行
print(ret) #返回的值是个地址就是个生成器
结果:<generator object func at 0x0000000000B99D00>

就是将函数中的return换成yield就是生成器,

return:直接返回结果,结束函数的调用

yield:返回结果,可以让函数分段执行.

1.如何执行生成器:

1)生成器的本质就是迭代器,所以可以用__next__()进行执行

def func():
    print('周杰伦')
    yield '昆凌'
    print('哈哈')
    yield '呵呵'
ret = func()
print(ret.__next__())
print(ret.__next__())
结果:周杰伦
    昆凌
    哈哈
    呵呵

注意:如果最后一个yield执行完毕,再次__next__()程序会报错

生成器的作用:省内存,可以一次去一个,一个个的指向下一个,不会回去,__next__()到哪,指针就指哪,下一次继续获取指针指向的值.

2.用send()方法:

def eat():
    print('我吃什么')
    a = yield '馒头'
    print('a=',a)
    b = yield'大饼'
    print('b=',b)
    c = yield'韭菜盒子'              
    print('c=',c)
    yield 'GAME OVER'
gen = eat() #获取生成器
print(gen.__next__())
print(gen.send('胡辣汤'))
print(gen.send('狗粮'))
print(gen.send('猫粮'))
结果:我吃什么
馒头
a= 胡辣汤
大饼
b= 狗粮
韭菜盒子
c= 猫粮
GAME OVER

send 和 __next__区别
1).send和next()都是让生成器向下走一次

2).send可以给上一个yield的位置传递值,不能给最后一个yield发送值,第一次执行生成器代码的时候不能使用send()

3.生成器本质上是迭代器,所以可以使用for循环取值

def func():
    print('哈哈')
    yield '呵呵'
    print('嘿嘿')
    yield '嘻嘻'
    print('呀呀')
    yield'花花'
ret = func()
for i in ret:
    print(i)

4.可以用列表list取值:

def func():
    print('哈哈')
    yield '呵呵'
    print('嘿嘿')
    yield '嘻嘻'
    print('呀呀')
    yield'花花'
ret = func()
print(list(ret))
结果:哈哈
    嘿嘿
    呀呀
['呵呵', '嘻嘻', '花花']

三.列表推导式,生成器表达式以及其他推导式

1)列表推导式:[结果 for 变量 in 可迭代对象 if 筛选]

例:给一个列表,通过循环,向列表中添加1-9

lst = []
for i in range(1,10)
    lst.append(i)
print(lst)

通过列表推导式:

lst = [i = for i in range(1,10)]
print(lst)

对列表中的数据进行筛选:[结果 for 变量 in 可迭代对象 if条件]

lst = [i fro i in range(1,101) if i%2 == 0]
print(lst)

2)生成器表达式:

生成器表达式和列表推导式的语法基本上一样,只是把[]替换()

gen = (i for i in range(100))
print(gen)
结果:<generator object <genexpr> at 0x0000000000A29D00>

打印结果是个生成器,可以用for循环来获取最终结果

gen = (i for i in range(100))
for i in gen:
    print(i)

生成器表达式也可以进行筛选,跟列表表达式一样,只是[]变成了()

生成器表达式和列表推导式的区别:

1.列表推导式比较耗内存,一次性加载,生成器表达式几乎不占内存,使用的时候才分配和使用内存.

2.得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器

生成器的惰性机制:生成器只有在访问的时候才取值,说白了,你找他要他才给你值,不找他要,他就不回执行.

def func():
    print(111)
    yield 222
g = func() # 生成器g
g1 = (i for i in g) # 生成器g1. 但是g1的数据来源于g
g2 = (i for i in g1) # 生成器g2. 来源g1
print(list(g)) # 获取g中的数据. 这时func()才会被执行. 打印111.获取到222. g完毕.
print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据了
print(list(g2)) # 和g1同理

神坑:生成器,要值的时候才拿值

3)字典推导式{结果 for 变量 in可迭代对象 if 筛选} 结果--->key:value

dic = {'a':'b','c':'d'}

把字典中的key和value互换

dic = {"a":"b", "c":"d"}
new_dic = {dic[key]:key for key in dic }
print(new_dic)

4)集合推导式:{结果 for 变量 in 可迭代对象 if 筛选}  结果--->key

集合推导式可以直接生成一个集合,集合特别,无序,不重复,所以集合推导式自带去重功能

lst = ["马化腾", "马化腾", "王建忠", "张建忠", "张建忠", "张雪峰", "张雪峰"]
s = {i for i in lst}    # 集合推倒式
print(s)

总结:推导式有:列表推导式,字典推导式,集合推导式,没有元祖推导式

  生成器表达式:(结果 for 变量 in 可迭代对象 if 筛选)

  生成器表达式可以直接获取到生成器对象,生成器可以直接进行for循环,生成器具有惰性机制

原文地址:https://www.cnblogs.com/ITdong-1/p/9329808.html