zoukankan      html  css  js  c++  java
  • Python 为什么要用yield

    可能听说过,带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ?我们先抛开 generator,以一个常见的编程题目来展示 yield 的概念。

    如何生成斐波那契數列

    斐波那契(Fibonacci)數列是一个非常简单的递归数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到。用计算机程序输出斐波那契數列的前 N 个数是一个非常简单的问题,许多初学者都可以轻易写出如下函数:

    1. 简单输出斐波那契數列前 N 个数

    def fab(max): 
        n, a, b = 0, 0, 1 
        while n < max: 
            print(b)
            a, b = b, a + b 
            n = n + 1
    fab(5)
    

     执行以上代码,我们可以得到如下输出:

    1

    1

    2

    3

    5

    结果没有问题,但有经验的开发者会指出,直接在 fab 函数中用 print 打印数字会导致该函数可复用性较差,因为 fab 函数返回 None,其他函数无法获得该函数生成的数列。要提高 fab 函数的可复用性,最好不要直接打印出数列,而是返回一个 List。以下是 fab 函数改写后的第二个版本:

    2. 输出斐波那契數列前 N 个数第二版

    def fab(max): 
        n, a, b = 0, 0, 1 
        L = [] 
        while n < max: 
            L.append(b) 
            a, b = b, a + b 
            n = n + 1 
        return L
     
    for n in fab(5): 
        print(n)
    

     可以使用如下方式打印出 fab 函数返回的 List:

    1

    1

    2

    3

    5

    改写后的 fab 函数通过返回 List 能满足复用性的要求,但是更有经验的开发者会指出,该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 iterable 对象来迭代。例如,在 Python2.x 中,代码:

    3. 通过 iterable 对象来迭代

    class Fab(object): 
     
        def __init__(self, max): 
            self.max = max 
            self.n, self.a, self.b = 0, 0, 1 
     
        def __iter__(self): 
            return self 
     
        def next(self): 
            if self.n < self.max: 
                r = self.b 
                self.a, self.b = self.b, self.a + self.b 
                self.n = self.n + 1 
                return r 
            raise StopIteration()
     
    for n in Fab(5): 
        print(n)
    

     Fab 类通过 next() 不断返回数列的下一个数,内存占用始终为常数:

    1

    1

    2

    3

    5

    然而,使用 class 改写的这个版本,代码远远没有第一版的 fab 函数来得简洁。如果我们想要保持第一版 fab 函数的简洁性,同时又要获得 iterable 的效果,yield 就派上用场了

    4. 使用 yield 的第四版

    def fab(max): 
        n, a, b = 0, 0, 1 
        while n < max: 
            yield b      # 使用 yield
            # print b 
            a, b = b, a + b 
            n = n + 1
     
    for n in fab(5): 
        print n
    

     简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

  • 相关阅读:
    进程与线程的区别与联系
    c 指针兼容性问题
    柔性数组
    Makefile之wildcard
    shell编程笔记1
    linux下gcc编译的参数详细说明
    的理解
    URL与URI的区别
    Log4J积累
    linux 查看磁盘、文件夹、文件大小(df du)
  • 原文地址:https://www.cnblogs.com/baxianhua/p/9990310.html
Copyright © 2011-2022 走看看