python生成器和生成器函数
Posted 月半王令
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python生成器和生成器函数相关的知识,希望对你有一定的参考价值。
1、生成器函数:
普通函数:
def func():
print("周杰伦")
return "昆凌"
func() #执行func()函数,"周杰伦"
print(func()) #执行结果:昆凌
生成器函数:
def func():
print("周杰伦")
yield "昆凌" # 函数中包含了yield, 当前这个函数就不再是普通的函数了. 是生成器函数
func() #通过func()函数生成一个生成器,非执行,没结果
print(func()) #打印的是该生成器函数所在的内存地址
#return 和yield的区别:
return: 执行到return时函数结束执行
yield:函数分段执行,从(当前yield到下一个yield]的内容
举例:
def func():
print("周杰伦")
yield "昆凌"
print("王力宏")
yield "李云迪"
#print("大家好才是真的好") #最后一个yield后不要写东西,因为__next__()找不到下一个yield时会报错StopIteration
g=func() #生成一个生成器
print(g.__next__()) #周杰伦 昆凌
print(g.__next__()) #王力宏 李云迪
2、send()
#__next__()和send()区别:
__next__() 可以让生成器向下执行一次;
send() 也可以让生成器向下执行一次, 给上一个yield传一个值, 第一个和最后一个yield不需要传值(最后一个值可以传进去但会报错)。
举例1:
def eat():
print("我吃什么啊")
a = yield "馒头"
print("a=",a)
b = yield "大饼"
print("b=",b)
c = yield "韭菜盒子"
print("c=",c)
yield "GAME OVER"
gen = eat() # 获取生成器
ret1 = gen. __next__ ()
print(ret1)
ret2 = gen.send("胡辣汤")
print(ret2)
ret3 = gen.send("狗粮")
print(ret3)
ret4 = gen.send("猫粮")
print(ret4)
执行结果:
我吃什么啊
馒头--------------第一次__next__()获取的内容
a= 胡辣汤----第一次send赋值,并打印
大饼-------第一次send获取的内容
b= 狗粮---第二次send赋值
韭菜盒子---第二次send获取的内容
c= 猫粮
GAME OVER
举例2:
def func():
print(‘0‘)
yield 1
print(‘2‘)
yield 3
yield 4
g1 = func()
lst = list(g1) #把生成器转换成列表
print(lst)
执行结果:
0
2
[1, 3, 4]
3、列表推倒式
语法:[最终结果 for 变量 in 可迭代对象 if 条件]
lst = [i for i in range(1,101) if i%2==0]
print(lst)
4、生成器表达式
#生成器表达式和列表推倒式基本是一样的,只是把[]换成()
语法:(最终结果 for 变量 in 可迭代对象 if 条件)
g = (i for i in range(10))
print(g) #打印的是通过表达式生成的生成器所在的内存地址
print(g.__next__()) #获取的第一个元素是0
print(list(g)) #获取的是列表 [0,1,2,3,4,5,6,7,8,9]
5、其他推倒式
5.1 字典推倒式:
语法:[结果(key:value) for 变量 in 可迭代对象 if 筛选]
#把字典中的key:value互换 .{"b":"a", "d":"c"}
dic = {"a":"b", "c":"d"}
new_dic = {dic[key]:key for key in dic}
print(new_dic)
5.2 集合推倒式:
语法:{结果(key) for 变量 in 可迭代对象 if 筛选}
lst = ["马化腾", "马化腾", "王建忠", "张建忠", "张雪峰", "张雪峰"]
s = {i for i in lst} # 集合推倒式,无序且不重复,自动去重
print(s)
注:没有元组推倒式(因为元组不可变,小括号括起来的是生成器表达式)
总结:
1、生成器的本质就是迭代器
2、生成器3种生成方法:
1)通过生成器函数
2)通过生成器表达式
3)通过数据转换
3、生成器函数被执行,如func()是拿到一个生成器函数,不是获取里面的内容
4、生成器取值:
1)__next__()
2)send()
3)for循环
4)list(g)
5、return 和yield的区别:
return: 执行到return时函数结束执行
yield:函数分段执行,从(当前yield到下一个yield]的内容
6、生成器惰性机制应用
举例1:
def func():
print(111)
yield 222
g = func() #生成器g
g1 = (i for i in g) #生成器g1,但数据来源g
g2 = (i for i in g1)#生成器g2,但数据来源g1
print(list(g)) #获取生成器g数据,此时func()才会被执行,打印111,获取到222
print(list(g1))#获取g1数据,来源g,但g数据已被取完,所以返回是空
print(list(g2))#同g1
执行结果:
111
[222]
[]
[]
举例2:若把print(list(g))注释了,得到的结果怎样?
def func():
print(111)
yield 222
g = func() #生成器g
g1 = (i for i in g) #生成器g1,但数据来源g
g2 = (i for i in g1)#生成器g2,但数据来源g1
#print(list(g))
print(list(g1))
print(list(g2))
执行结果:
111
[222]
[]
举例3:
def add(a,b):
return a + b
def test():
for i in range(4):
yield i
g = test() #0,1,2,3,
for n in [2,10]: #n 取值2,10 表示共循环2次
g=(add(n,i) for i in g)
print(list(g))
#list(g)时才会执行,生成器惰性特质
#g=(add(n,i) for i in g) 循环2次,相当于最后g=(add(n,i) for i in (add(n,i) for i in g))
#g=(add(n,i) for i in (add(n,i) for i in (0,1,2,3)))
#生成器不到最后不执行,最后一次n=10,那么g=(add(10,i) for i in (10,11,12,13))
#g=[20,21,22,23]
以上是关于python生成器和生成器函数的主要内容,如果未能解决你的问题,请参考以下文章