前几天刚开始看 Python ,后因为项目突然到来,导致Python的学习搁置了几天。然后今天看回Python 发现 Yield 这个忽然想不起是干嘛用的了(所以,好记性不如烂笔头。)。然后只能 花点时间 回顾一下 廖雪峰老师 Python前面的课程内容了 并对廖老师的课程内容做了以下总结:
迭代器(iter):迭代器是访问集合元素的一种方式。迭代器的对象从集合的第一个元素开始访问,直到所有的元素被访问结束。迭代器只能往前不会退后。
不过也没什么,因为很少在迭代过程中往后退。另外迭代器一大优点是不需要准备好整个迭代过程中的所有元素。迭代器仅仅在迭代
到某个元素时才计算该元素,而在这之前或者之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或者无限的集合
,比如几个G的文件。
生成器(generator):一个函数返回一个迭代器,那这个函数就叫做生成器(generator),如果函数中包含yield语法,那这个函数就变成生成器。
Yield:yield的主要作用就是可以使函数中断,并保存中断状态,中断后,代码可以继续往下执行,过一段时间还可以重新调用这个
函数,从上次yield的下一句开始执行。
首先,先来看一个“斐波那契数列”(从第三个数开始,每位的值都等于前两个数的和)的例子
def Fibonacci(max): n , a, b = 0 , 0 , 1 while n < max: print(b) a , b = b, a + b n = n + 1 # 输出前十位 Fibonacci(10)
得出的结果:
E:Python>python test.py
1
1
2
3
5
8
13
21
34
55
PS: Fibonacci 这个函数大家有没有发现一个问题, 这个函数是没有返回值的,也就是说,基本上是无法复用的。如果要提高 fab 函数的可复用性,那么要怎么做的?
用一个List 把要输出的值保存下来。如下:
def Fibonacci(max): n , a, b = 0 , 0 , 1 len = [] while n < max: len.append(b) a , b = b, a + b n = n + 1 return len # 调用函数 for n in Fibonacci(10): print(n)
输出结果:
1 1 2 3 5 8 13 21 34 55
PS: 如上就是我们经常看到的函数, 但是有经验的开发者们会发现一个问题, 内存问题, 如果 max的大小和 占用内存的大小是成正比的,也就是说max越大,占用资源就越多。
这个时候使用 Yield 使得函数返回值变成迭代器来解决这个问题,如下例子:
def Fibonacci(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, b + a n = n + 1 # 调用返回 for n in Fibonacci(10): print(n)
输出结果:
1 1 2 3 5 8 13 21 34 55
PS:上面Fibonacci 返回的就是一个迭代器。
肯定有小伙伴会问道,迭代器的原理是什么?
1 def Fibonacci(max): 2 n, a, b = 0, 0, 1 3 while n < max: 4 yield b 5 a, b = b, b + a 6 n = n + 1
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return
语句或者最后一行函数语句就返回。
而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
也就是第一次next 生成器函数 只执行到 第四行(yield b)
这个时候再执行一次 next 那么生成器函数会从第五行还是执行。 就是这样一步步推算下来。
当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。
以上。
如果有什么讲的不好地方,希望大家批评指正。