【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]

 

猜你喜欢

转载自www.cnblogs.com/xlzhangq/p/13211155.html