Python学习----高级特性
来源:互联网 发布:淘宝开店无忧是真的吗 编辑:程序博客网 时间:2024/05/16 11:47
高级特性
四、生成器
1.generator基础
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
>>> L = [x * x for x in range(10)]>>> L[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]>>> g = (x * x for x in range(10))>>> g<generator object <genexpr> at 0x1022ef630>
创建L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
>>> next(g)0>>> next(g)1>>> next(g)4
generator保存的是算法,每次调用next(g)
,就计算出g
的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return 'done'
这就是定义generator的另一种方法。如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> fg = fib(6)>>> fg<generator object fib at 0x104feaaa0>
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return
语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
举个简单的例子,定义一个generator,依次返回数字1,3,5:
def even(): print('step 1') yield (2) print('step 2') yield(4) print('step 3') yield(6)
调用该generator时,首先要生成一个generator对象,然后用next()
函数不断获得下一个返回值:
>>> e = even()>>> next(e)step 12>>> next(e)step 24>>> next(e)step 36>>> next(e)Traceback (most recent call last): File "<stdin>", line 1, in <module>StopIteration
可以看到,even
不是普通函数,而是generator,在执行过程中,遇到yield
就中断,下次又继续执行。执行3次yield
后,已经没有yield
可以执行了,所以,第4次调用next(e)
就报错。
回到fib
的例子,我们在循环过程中不断调用yield
,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。
把函数改成generator后,我们基本上从来不会用next()
来获取下一个返回值,而是直接使用for
循环来迭代:
>>> for n in fib(6):... print(n)...112358
但是用for
循环调用generator时,发现拿不到generator的return
语句的返回值。如果想要拿到返回值,必须捕获StopIteration
错误,返回值包含在StopIteration
的value
中:
>>> fg = fib(6)>>> while True:... try:... x = next(fg)... print('fg:', x)... except StopIteration as e:... print('Generator return value:', e.value)... break...g: 1g: 1g: 2g: 3g: 5g: 8Generator return value: done
2.打印杨辉三角
[1][1, 1][1, 2, 1][1, 3, 3, 1][1, 4, 6, 4, 1][1, 5, 10, 10, 5, 1][1, 6, 15, 20, 15, 6, 1][1, 7, 21, 35, 35, 21, 7, 1][1, 8, 28, 56, 70, 56, 28, 8, 1][1, 9, 36, 84, 126, 126, 84, 36, 9, 1]参考:
def triangles(n): L = [1] while len(L) < n + 1: yield(L) L.append(0) L = [L[i] + L[i - 1] for i in range(len(L))] //到这一步,L[-1]总是0。原因为上一步的append操作for i in triangles(10): print(i)
- Python学习----高级特性
- Python学习-高级特性
- Python学习07:高级特性
- Python学习V---高级特性
- Python学习笔记--高级特性
- Python学习6-高级特性
- Python学习系列:高级特性
- python学习7-------高级特性
- python学习之高级特性
- python学习笔记----高级特性
- 【Python学习笔记】python高级特性:切片
- 【Python学习笔记】python高级特性:生成器
- 【Python学习笔记】python高级特性:迭代器
- python学习笔记(三) - 高级特性
- Python之学习笔记(高级特性)
- python学习记录(2)高级特性
- python学习(三):高级特性
- Python学习笔记(三)高级特性
- Easyui Treegrid 上下移动实现
- 文章标题
- Bootstrap学习:超大屏幕
- 10g Manual Database Creation in Oracle (Single Instance and RAC) (文档 ID 240052.1)
- UI设计——动画设计
- Python学习----高级特性
- iOS 的一种设计模式 类别 catagory
- 1358(Period)字符串匹配-KMP
- Application, Activity, task的区别
- Struts2的struts.xml中配置及通配符的使用
- 青春不完美,才懂珍惜
- java实现区域内屏幕截图示例
- linux常用命令
- 从程序员的角度来看为什么我们需要工作流 .