生成器

Posted yanranran

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生成器相关的知识,希望对你有一定的参考价值。

生成器

什么是个生成器:生成器本质就是迭代器

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

  1.通过生成器函数

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

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

# 简单的函数
def func():
    print(这是函数func)
    return 这是函数func,return
print(func())
结果:
这是函数func
这是函数func,return

# 生成器
def func():
    print(这是函数func)
    yield 这是函数func,yield
print(func())
结果:
<generator object func at 0x00000000024AFE08>

运行的结果不一样,为什么呢?? 由于函数中存在yield,那么这个函数就是一个生成器函数.

我们在执行这个函数的时候.就不再是函数的执行了.而是获取这个生成器.如何使用???

想想迭代器,生成器的本质就是迭代器.所以我们可以直接执行__next__()来执行以下生成器

def func():
     print("111")
     yield 222
gener = func() # 这个时候函数不会执行,而是是获取到生成成器
ret = gener.__next__() # 这个时候函数才会执行. yield的作用和return一样. 也是返回数据
print(ret)
结果:
111
222

那么我们可以看到,yield和return的效果是一样的,但是还是有点区别

  yield是分段来执行一个函数

  return是直接停止这个函数

def func():
    print("111")
    yield 222
    print("333")
    yield 444
 
 
gener = func()
ret = gener.__next__()
print(ret)
ret2 = gener.__next__()
print(ret2)
ret3 = gener.__next__()
# 最后一个yield执行完毕. 再次__next__()程序报错
print(ret3)
结果:
111
222
333
444

 

当程序运行完最后一个yield,那么后面继续运行__next__()程序会报错

我们来看一下这个需求,老男孩向楼下卖包子的老板订购了10000个包子.包子铺老板实在一下就全部都做出来了

def eat():
    lst = []
    for i in range(1,10000):
        lst.append(包子+str(i))
    return lst
e = eat()
print(e)

这样做是没有问题但是我们目前这么点人吃不完这么多,只能先放到一个地方,要是能够我吃一个老板做一个就完美了.

def eat():
    for i in range(1,10000):
        yield 包子+str(i)
e = eat()
print(e.__next__())
print(e.__next__())
print(e.__next__())
print(e.__next__())
print(e.__next__())
print(e.__next__())

上下的区别: 第一种是直接把包子都拿来,很占内存也就是很占咱们的位置,第二种使用生成器,想吃就拿一个.吃多少个包多少个.生成器是一个一个的,一直向下进行,不能向上.__next__()到哪,指针就指到哪儿.下一次继续就获取指针指向的值

send方法

send和__next__()一样都可以让生成器执行到下一个yield

def eat():
    for i in range(1,10000):
        a = yield 包子+str(i)
        print(a is,a)
 
        b = yield 窝窝头
        print(b is, b)
e = eat()
print(e.__next__())
print(e.send(大葱))
print(e.send(大蒜))

send和__next__()区别:

send 和 next()都是让生成器向下走一次

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

第一次调用的时候使用send()也可以但是send的参数必须是None

def func1():
    print(这是函数func1)
    f1 = yield 你好
    print(f1)
    f2 = yield 我好
    print(f2)
f = func1()
f.__next__()   #注意此处的输出方式
f.send(大家好)

 

 

yield from

在python3中提供一种可以直接把可迭代对象中的每一个数据作为生成器的结果进行返回

def func():
    lst = [卫龙,老冰棍,北冰洋,牛羊配]
    yield from lst
g = func()
for i in g:
    print(i)

有个小坑,yield from 是将列表中的每一个元素返回,所以 如果写两个yield from 并不会产生交替的效果

def func():
    lst1 = [卫龙,老冰棍,北冰洋,牛羊配]
    lst2 = [馒头,花卷,豆包,大饼]
    yield from lst1
    yield from lst2
     
g = func()
for i in g:
    print(i)

 

以上是关于生成器的主要内容,如果未能解决你的问题,请参考以下文章

Apollo Codegen 没有找到生成代码的操作或片段

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

vscode代码片段生成vue模板

VS Code配置snippets代码片段快速生成html模板,提高前端编写效率

vs 2010代码片段