我正在参与「掘金启航计划」

写在之前

在之前的文章(零根底学习 Python 之初识生成器)中咱们留了这么一个问题:“yield 除了作为生成器的标志以外,还有一个「返回值」的功用,咱们知道 return 也有这个功用,那么它跟 return 的这个返回值有什么差异呢”?今日咱们就来学学这个 yield,趁便解决掉这个问题。

yield

为了搞清楚 yield 和 return 这两者的差异,咱们先来看一个简略的例子:

>>> def self_return(n):
...    print('rocky')
...    while n > 0:
...            print('before return')
...            return n
...            n -= 1
...            print('after return')
...
>>> s = self_return(3)
rocky
before return
>>> s
3

从上面的例子中函数 self_return(n) 被调用的过程中咱们能够明晰的看出,s = self_return(3) 函数体内的句子就开端履行了,遇到 return 以后将值返回,并完毕在函数体内的履行,所以咱们看到的成果是 return 后面的句子根本没有履行,这个是 return 的特色,不知道你还记得么?假如不记得的话能够去翻我前面的文章。

下面咱们来将 return 换乘 yield ,再来试试看:

>>> def self_yield(n):
...    print('rocky')
...    while n > 0:
...            print('before yield')
...            yield n
...            n -= 1
...            print('after yield')
...
>>> s = self_yield(3)
>>> s.__next__()
rocky
before yield
3

仔细观察上面的例子你会发现,s = self_yield(n) 并没有去履行函数体内的句子,且 s.next() 的时分遇到 yield 的时分,会返回值,而且暂停。咱们接着再持续来试一下:

>>> s.__next__()
after yield
before yield
2
>>> s.__next__()
after yield
before yield
1
>>> s.__next__()
after yield
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
StopIteration

经过上面的持续操作,咱们能够看到每次遇到 yield 的时分都会返回值,而且暂停,下次再履行的时分是从上次暂停的位置开端又持续履行的,当没有满足条件的值,就会抛出异常。

结合上面的剖析和对用例的履行成果,相信你现已你现已理解了 yield 的特色,也知道它与 return 之间的差异了:一般的函数,都是止于 return;作为生成器的函数,由于有了 yield,则遇到它会挂起。

下面我想再用一个例子来具体的阐述一下。斐波那契数列相信你们现已不陌生了,我在前面的文章中不止一次的提过它,这次咱们测验将 yield 应用到斐波那契数列中:

def fibs(max):
   """
   fibonacci sequence generator
   """
   n, a, b = 0, 0, 1
   while n < max:
       yield b
       a, b = b, a + b
       n += 1
if __name__ == "__main__":
   f = fibs(9)
   for i in f:
       print(i,end = ' ')

上述代码的运转成果如下:

1 1 2 3 5 8 13 21 34 55

你看,用生成器生成的斐波那契数列是不是跟以前的不一样了呢?假如有兴趣的话,你能够将我在前面文章中演示过的斐波那契数列的实现方式和现在的做一下对比,然后仔细观察一下差异之处。

经过这几回的各种演示,其实现已很清晰了:在一个函数中假如有了 yield 句子,那么它就是生成器,即也是迭代器。这种方式比前面写迭代器的类要简洁的多,但这不是说迭代器欠好,无论是运用迭代器还是生成器都要具体问题具体剖析。

公众号:程序员喵大人,最新咨询分享,爬虫,数据剖析,办公自动化等学习分享,欢迎来撩