首页IT科技python生成器作用(深入理解Python中的生成器)

python生成器作用(深入理解Python中的生成器)

时间2025-09-19 08:25:37分类IT科技浏览7600
导读:通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列...

通过列表生成式                ,我们可以直接创建一个列表                。但是                             ,受到内存限制          ,列表容量肯定是有限的                             。而且            ,创建一个包含100万个元素的列

表                            ,不仅占用很大的存储空间               ,如果我们仅仅需要访问前面几个元素        ,那后面绝大多数元素占用的空间都白白浪费了          。

所以                           ,如果列表元素可以按照某种算法推算出来                    ,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list    ,从而节省大量的空间            。在Python中                          ,这种一边循环一边计算的机制                         ,称为生成器(Generator)                            。

要创建一个generator,有很多种方法               。第一种方法很简单                     ,只要把一个列表生成式的[]改成()                              ,就创建了一个generator:

>>>L=[x*xforxinrange(10)]>>>L [0,1,4,9,16,25,36,49,64,81]>>> g=(x*xforxinrange(10))>>>g <generatorobject<genexpr>at0x104feab40>

创建L和g的区别仅在于最外层的[]和()     ,L是一个list                ,而g是一个generator        。

我们可以直接打印出list的每一个元素                             ,但我们怎么打印出generator的每一个元素呢?

如果要一个一个打印出来          ,可以通过generator的next()方法:

>>>g.next() >>>g.next() 1 >>>g.next() 4 >>>g.next() 9 >>>g.next() 16 >>>g.next() 25 >>>g.next() 36 >>>g.next() 49 >>>g.next() 64 >>>g.next() 81 >>>g.next() Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> StopIteration

我们讲过            ,generator保存的是算法                            ,每次调用next()               ,就计算出下一个元素的值        ,直到计算到最后一个元素                           ,没有更多的元素时                    ,抛出StopIteration的错误                           。

当然    ,上面这种不断调用next()方法实在是太变态了                          ,正确的方法是使用for循环                         ,因为generator也是可迭代对象:

>>>g=(x*xforxinrange(10)) >>>forning: ...printn ... 1 4 9 16 25 36 49 64 81

所以,我们创建了一个generator后                     ,基本上永远不会调用next()方法                              ,而是通过for循环来迭代它                    。

generator非常强大    。如果推算的算法比较复杂     ,用类似列表生成式的for循环无法实现的时候                ,还可以用函数来实现                          。

比如                             ,著名的斐波拉契数列(Fibonacci)          ,除第一个和第二个数外            ,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来                            ,但是               ,用函数把它打印出来却很容易:

deffib(max): n,a,b=0,0,1 whilen<max:printb a,b=b,a+b n=n+1

上面的函数可以输出斐波那契数列的前N个数:

>>>fib(6) 1 1 2 3 5 8

仔细观察        ,可以看出                           ,fib函数实际上是定义了斐波拉契数列的推算规则                    ,可以从第一个元素开始    ,推算出后续任意的元素                          ,这种逻辑其实非常类似generator                         。

也就是说                         ,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print b改为yield b就可以了:

deffib(max): n,a,b=0,0,1 whilen<max: yieldb a,b=b,a+b n=n+1

这就是定义generator的另一种方法                     。如果一个函数定义中包含yield关键字                     ,那么这个函数就不再是一个普通函数                              ,而是一个generator:

>>>fib(6) <generatorobjectfibat0x104feaaa0>

这里     ,最难理解的就是generator和函数的执行流程不一样                              。函数是顺序执行                ,遇到return语句或者最后一行函数语句就返回     。而变成generator的函数                             ,在每次调用next()的时候执行          ,遇到yield语句返回            ,再次执行时从上次返回的yield语句处继续执行                。

举个简单的例子                            ,定义一个generator               ,依次返回数字1        ,3                           ,5:

>>>defodd(): ...printstep1 ...yield1 ...printstep2 ...yield3 ...printstep3 ...yield5 ... >>>o=odd() >>>o.next() step1 1 >>>o.next() step2 3 >>>o.next() step3 5 >>>o.next() Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> StopIteration

可以看到                    ,odd不是普通函数    ,而是generator                          ,在执行过程中                         ,遇到yield就中断,下次又继续执行                             。执行3次yield后                     ,已经没有yield可以执行了                              ,所以     ,第4次调用next()就报错          。

回到fib的例子                ,我们在循环过程中不断调用yield                             ,就会不断中断            。当然要给循环设置一个条件来退出循环          ,不然就会产生一个数列出来                            。

同样的            ,把函数改成generator后                            ,我们基本上从来不会用next()来调用它               ,而是直接使用for循环来迭代:

>>>forninfib(6): ...printn ... 1 1 2 3 5 8

小结

generator是非常强大的工具        ,在Python中                           ,可以简单地把列表生成式改成generator                    ,也可以通过函数实现复杂逻辑的generator               。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
获取python的运行结果(3分钟学会python获取当前运行文件路径的方法)