python用迭代器,生成器完成斐波那契数列

        我们发现迭代器最核心的功能就是可以通过next()函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。

        数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到,具体如下:

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

现在我们想要通过for...in...循环来遍历迭代斐波那契数列中的前n个数。那么这个斐波那契数列我们就可以用迭代器来实现,每次迭代都通过数学计算来生成下一个数。

# 定义迭代器
class Fibonacci(object):
    # num:表示生成fibonacci数列的个数
    def __init__(self, num):
        self.num = num
        # 保存前两个值
        self.a = 0
        self.b = 1
        # 记录生成数列的下标
        self.current_index = 0

    def __iter__(self):
        return self

    # 生成下一个数据
    def __next__(self):
        if self.current_index < self.num:
            result = self.a
            self.a, self.b = self.b, self.a + self.b
            self.current_index += 1
            return result
        else:
            raise StopIteration

# 创建迭代器
fib = Fibonacci(5)
# # 获取迭代器中下一个值
# result = next(fib)
# print(result)

# 直接遍历迭代器
for value in fib:
    print(value)
 
 

执行结果:

0
1
1
2
3
 
 

当然如果你了解到了yield的工作原理了,我们就可以用特殊的迭代器,也就是生成器来完成这个看似复杂的斐波那契的迭代了

  • 使用了yield关键字的函数不再是函数,而是生成器。(使用了yield的函数就是生成器)
  • yield关键字有两点作用:
    • 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起
    • 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return的作用
  • 可以使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)
  • Python3中的生成器可以使用return返回最终运行的返回值,而Python2中的生成器不允许使用return返回一个返回值(即可以使用return从生成器中退出,但return后不能有任何表达式)。
# 创建生成器的第二种方式->在def里面看到yield关键字表示就是一个生成器

# 定义生成器
def fibonacci(num):
    # num: 表示斐波那契数列的个数
    # 保存前两个值
    a = 0
    b = 1
    # 记录生成数列的下标
    current_index = 0
    print("----11----")
    # 循环判断条件是否成立
    while current_index < num:
        # 生成下一个斐波那契数列
        result = a
        a, b = b, a + b
        current_index += 1
        print("----22----")
        # 代码执行到yield会暂停,把结果返回出取,再次启动生成器的时候会在暂停的位置继续往下执行
        yield result
        print("----33----")


f = fibonacci(5)
# value = next(f)
# print(value)
#
# value = next(f)
# print(value)

for value in f:
    print(value)
 
 

执行结果如下:

----11----
----22----
0
ok
----33----
----22----
1
在使用生成器实现的方式中,我们将原本在迭代器 __next__ 方法中实现的基本逻辑放到一个函数中来实现,但是将每次迭代返回数值的return换成了yield,此时新定义的函数便不再是函数,而是一个 生成器 了。 简单来说:只要在def中有yield关键字的 就称为 生成器

猜你喜欢

转载自blog.csdn.net/feilzhang/article/details/80220405