美文网首页
yield(对比return)

yield(对比return)

作者: juriau | 来源:发表于2018-09-26 17:08 被阅读174次

带有 yield 的函数在 Python 中被称之为 generator(生成器),returnyield的形式和用法很相像,下面以Fibonacci数列来对比一下yieldreturn

如何生成斐波那契數列

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

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

执行 fab(5),我们可以得到如下输出:


image.png

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

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

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


image.png

改写后的 fab 函数通过返回 List 能满足复用性的要求,但是更有经验的开发者会指出,该函数在运行中占用的内存会随着参数 max 的增大而增大,如果要控制内存占用,最好不要用 List来保存中间结果,而是通过 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.b = self.a + self.b
           self.a = self.b - self.a
           self.n = self.n + 1 
           return r 
       raise StopIteration()

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

image.png

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

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

第四个版本的 fab 和第一版相比,仅仅把 print b 改为了 yield b,就在保持简洁性的同时获得了 iterable 的效果。
调用第四版的 fab 和第二版的 fab 完全一致:

image.png

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

image.png

当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。


更多Fibnocci数列

def fib(x):
    if(x==1 || x==2):
        return 1
    else:
        return fib(x-1)+fib(x-2)
def fib(max): 
   n, a, b = 0, 0, 1 
   while n < max: 
       yield b 
       a, b = b, a + b 
       n = n + 1

相关文章

  • yield(对比return)

    带有 yield 的函数在 Python 中被称之为 generator(生成器),return和yield的形式...

  • koa 和 ES6

    构造器的写法 yield的作用yield类似return,但是在一般函数中,return只能一次。但是yield在...

  • yield

    yield不可单独使用 需要与return配合使用,例如: 1 yield return 0; //等0帧 2 y...

  • python yield 和 return 对比分析

    相同点:都是返回函数执行的结果 不同点:return 在返回结果后结束函数的运行,而yield 则是让函数变成一个...

  • python中的yield与return

    yield与return的功能都是返回程序执行结果,但是yield返回执行结果并不中断程序执行,return在返回...

  • python-复盘-yield & return区别

    python-复盘-yield & return区别

  • Yield

    yield is a keyword that is used like return, except the f...

  • yield vs return

    Obviously, generator can boost the performance by saving ...

  • yield和return

    1、.print并不会阻断程序的执行,就不用多说了。 2、func2()方法中的循环执行第一次就被return结束...

  • async await 和yield from

    yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:...

网友评论

      本文标题:yield(对比return)

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