您的位置:首页 > 编程语言 > Python开发

Python 生成器与迭代器 yield 案例分析

2017-01-06 17:42 585 查看
前几天刚开始看 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 异常,循环会正常结束。

以上。

如果有什么讲的不好地方,希望大家批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: