python斐波那契数列生成器_python迭代器和生成器总结——新的斐波那契数列

给定一个集合,循环对集合中的每个元素应用某个操作,称之为迭代。

python迭代器

题目:给定一个序列,循环输出序列中的每个元素。

通过一个for循环就可以实现,如下:

for循环遍历

以上demo中,我们使用了print函数的双参数形式,通过第二个参数end,指定以一个空格作为结尾,以代替原来的换行。控制台结果如下:

for循环遍历结果

事实上,python中,提供了另一个工具来帮助遍历,该工具称之为迭代器。可以通过iter函数来获取一个迭代器,通过next函数来获取下一个元素。如下:

迭代器

上面的demo里,通过iter函数获取到了一个迭代器,再通过调用和序列元素个数相同次数的next函数,来不断通过迭代器取出序列中的元素。这里,也展示了next方法的特性,即每次调用,都会向后移一位。使得下次取出的是下一个元素。

demo里,通过序列元素的个数,限制了next函数调用的次数。假设没有限制,那么就会可能发生next不断后移,超出序列元素个数的情况,此时会发生什么呢?我们用如下代码测试:

无限next

得到如下结果:

StopIteration

我们看到,在控制台上,得到了一个异常,StopIteration,即停止迭代。

事实上,不需要range和len函数的帮助,可以直接通过for来对一个迭代器进行遍历,就像遍历原来的序列一样,如下:

for循环遍历迭代器

python迭代器的意义

有同学可能会有疑问:既然通过for循环就可以遍历一个序列,为什么又要来一个迭代器呢?

事实上,for循环能够正常运行的基础,就是因为相应的类实现了迭代器。

换句话说,假设有一个我们自己定义类,想让for循环可以作用于该类的对象,就需要为该类实现迭代器。一种实现方式是提供两个方法,分别是__iter__和__next__。

假设我们定义一个类A,并不提供__iter__和__next__方法,然后创建一个A类的对象a,尝试使用for循环对a进行遍历。如下:

遍历1

结果1

结果是我们得到了一个TypeError,类型错误。

我们尝试在类A中添加__iter__和__next__方法,如下:

遍历2

我们在控制台得到了不断输出的1。如下:

结果2

由以上demo可知,for语句的本质其实是不断对next的调用,其中的x,就是next的返回值。那么,是不是__iter__方法不重要呢?事实上,当将__iter__方法删除后,还是会得到一个TypeError,这说明,__iter__方法是重要的。

demo里,__next__方法简单返回了一个1,事实上,在真正使用时,这个方法可能需要更加丰富的逻辑。比如说,返回一个从1开始不断递增的数字序列,并且当大于10时,停止循环 。代码如下:

遍历3

结果如下:

结果3

上面的demo中,使用了类定义,对象创建,类变量,类方法,异常抛出等内容,如果有不理解的同学,我们后面的文章会聊到。

python生成器

前面的demo里,通过给一个类添加__iter__和__next__方法,使得该类的对象可以通过for语句来遍历。那么,假设我们有一个test方法,我们希望test方法的返回值可以被for语句遍历,该怎么写?比如下面这样:

错误的方法返回值遍历

这种方案显然是不行的,运行时会报TypeError。但是,比如说,我们直接返回一个序列类型的对象,如下:

返回序列

这种方案显然是可以的,但是,这显得有些投机取巧,且不具有通用性。python提供了一种生成器的机制,可以使方法返回值为一个迭代器,我们称之为生成器,即生成迭代器的工具。通过yield语句来实现,如下:

yield生成器

运行代码,发现可以正常运行,控制台输出了1。可以验证,yield确实可以生成一个迭代器并返回。那么,如何利用它来实现更丰富的功能呢?我们尝试实现一个递增的数字序列,返回1到10。如下:

生成器实现递增序列

运行程序,发现正确得到了从1到10的递增序列。

yield语句的作用是,当执行到yield时,会保存现场(各个变量的值),并返回一个迭代器。当再次执行时,yield前面的代码将不会再次执行,将直接从yield语句后面的代码开始执行。在上面的demo里,由于我们用了一个while True无限循环,所以,每次当a += 1执行完后,会再次循环执行到yield a。直接 a > 10。

前面一篇文章里我们聊到了斐波那契数列的demo,当时一个用for循环实现的代码如下:

斐波那契数列1

demo里,我们在for语句块的上面,定义了三个变量,分别是lastOne,lastTwo和current,这样做的原因是为了保存每次循环后,lastOne和lastTwo的结果。

利用生成器,我们可以以下面的方式得到斐波那契数列。代码如下:

斐波那契数列2

观察上面的代码,test是一个方法,它是可以接收参数的,中间变量的声明也可以简化,while循环也可以优化,最终我们可以得到一个更简洁且更具有通用性的代码:

斐波那契数列3

显然,fbnq方法可以接收一个参数,该参数可以控制输出序列前n项。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值