美文网首页
Python高频面试题——生成器(最通俗的讲解)

Python高频面试题——生成器(最通俗的讲解)

作者: 测试开发Kevin | 来源:发表于2023-03-08 14:06 被阅读0次


    生成器定义

    在 Python 中,使用了 yield 的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时,从当前位置继续运行。yield 函数创建生成器generator。yield相当于 return 返回一个值,并且记住这个返回的位置,下次迭代时,代码从

    yield的下一条语句开始执行,代码如下:

    def num_generator2():

        yield 1

        yield 2

        yield 3

    gen2 = num_generator2()

    print(next(gen2))

    print(next(gen2))

    print(next(gen2))

    print(next(gen2))

    输出:

    print(next(gen2))

    StopIteration

    1

    2

    3

    上面的代码中我们可以看到:

    num_generator2() 是生成器函数,而gen2 是生成器对象;

    调用一次next 输出一个值,生成器会记录前一次next的执行位置

    当next无值时,抛出异常StopIteration

    print(type(gen2)) 输出<class 'generator'>

    因为通过next函数可以获取生成器对象的值,所以生成器对象就是迭代器对象 执行下面代码可以证明

    from collections.abc import Iterator

    print(isinstance(gen2,Iterator))

    返回True

    再看一个经典的例子

    def demo():

        while True:

              val = yield 1

              print("val:", val)

    g = demo()

    print("第一次执行")

    print(next(g))

    print("第二次执行")

    print(next(g))

    print("第三次执行")

    print(g.send(2))

    输出:

    第一次执行

    1

    第二次执行

    val: None

    1

    第三次执行

    val: 2

    1

    对上面的例子进行一下分析

    第一次执行输出

    1

    返回了1,因为 val = yield 1 执行后,程序就结束了,所以 print("val:", val)没有被执行

    第二次执行输出

    val: None

    1

    因为记录了上次执行的位置,所以val: None是while上面的print的结果(val没有赋值,所以是None),第二个是return的结果还是1

    第三次执行输出

    val: 2

    1

    这里使用了send方法,就是发送一个参数给val,这次 print("val:", val)中的参数val 首先被赋值了2进行了输出,然后在return 1

    使用生成器的原因

    为什么使用generator呢,最重要的原因是可以按需生成并“返回”结果,而不是一次性产生所有的返回值。比如对于下面的代码。

    NUM = 100

    for i in [x*x for x in range(NUM)]: # 第一种方法:对列表进行迭代

        print(i)

    for i in (x*x for x in range(NUM)): # 第二种方法:对generator进行迭代

        print (i)

    上面的代码中,两个for语句输出是一样的,代码字面上看来也就是中括号与小括号的区别(创建生成器的一个简单方法是把列表生成式的 [ ] 变为 ( ))。但这点区别差异是很大的,第一种方法返回值是一个列表,第二个方法返回的是一个generator对象。随着NUM的变大,第一种方法返回的列表也越大,占用的内存也越大;但是对于第二种方法没有任何区别,生成器一次只能返回一个值,将大大减小占用内存。

    生成器和迭代器的区别

    熟悉迭代器的同学发现,生成器和迭代器很像,但必定还是两个东东,二者的主要区别如下:

    1. 迭代器是访问容器的一种方式,容器已经出现,我们是从已有元素获取一份副本来为我们此次迭代使用;而生成器则是自己生成元素的。

    2. 在用法上生成器只需要简单函数写法,配合yield就能实现;而迭代器真正开发中使用有限

    return和yield的区别

    主要有两点

    return作为结尾的普通函数直接返回所有结果,程序终止不再运行,并销毁局部变量;

    yield会产生一个断点,暂停函数,挂起函数,保存当前状态。并且在yield处返回某个值,返回之后程序就不再往下运行了。

    具体的解释

    带yield的函数是一个生成器,而不是一个函数了,这个生成器有一个函数就是next函数,next就相当于“下一步”生成哪个数,这一次的next开始的地方是接着上一次的next停止的地方执行的,所以调用next的时候,生成器并不会从函数的开始执行,只是接着上一步停止的地方开始,然后遇到yield后,return出要生成的数,此步就结束。

    相关文章

      网友评论

          本文标题:Python高频面试题——生成器(最通俗的讲解)

          本文链接:https://www.haomeiwen.com/subject/qdkoldtx.html