python学习之路(14)
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> g=(x*x for x in range(10))
>>> g
<generator object <genexpr> at 0x05E42DF0>
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
如果要一个一个打印出来,可以通过generator的next()方法:
我们讲过,generator保存的是算法,每次调用next(),就计算出下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
当然,上面这种不断调用next()方法实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:
>>> for n in g:
print(n) 1
4
9
16
25
36
49
64
81
所以,我们创建了一个generator后,基本上永远不会调用next()方法,而是通过for循环来迭代它。
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
def fib(max):
n,a,b=0,0,1
while n<max:
print(b)
a,b=b,a+b
n=n+1
上面的函数可以输出斐波那契数列的前N个数:
>>> fib(6)
1
1
2
3
5
8
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print b改为yield b就可以了:
def fib(max):
n,a,b=0,0,1
while n<max:
yield b
a,b=b,a+b
n=n+1
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
>>> fib(5)
<generator object fib at 0x06282970>
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
举个简单的例子,定义一个generator,依次返回数字1,3,5:
>>> def odd():
... print 'step 1'
... yield 1
... print 'step 2'
... yield 3
... print 'step 3'
... yield 5
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
可以看到,odd不是普通函数,而是generator,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next()就报错。
回到fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。
同样的,把函数改成generator后,我们基本上从来不会用next()来调用它,而是直接使用for循环来迭代:
>>> for n in fib(6):
... print n
...
1
1
2
3
5
8
小结
generator是非常强大的工具,在Python中,可以简单地把列表生成式改成generator,也可以通过函数实现复杂逻辑的generator。
要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
python学习之路(14)的更多相关文章
- Python学习之路14☞多线程与多进程
一 进程与线程的概念 1.1 进程 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数 ...
- python学习之路-day2-pyth基础2
一. 模块初识 Python的强大之处在于他有非常丰富和强大的标准库和第三方库,第三方库存放位置:site-packages sys模块简介 导入模块 import sys 3 sys模 ...
- Python学习之路-Day2-Python基础3
Python学习之路第三天 学习内容: 1.文件操作 2.字符转编码操作 3.函数介绍 4.递归 5.函数式编程 1.文件操作 打印到屏幕 最简单的输出方法是用print语句,你可以给它传递零个或多个 ...
- Python学习之路【第一篇】-Python简介和基础入门
1.Python简介 1.1 Python是什么 相信混迹IT界的很多朋友都知道,Python是近年来最火的一个热点,没有之一.从性质上来讲它和我们熟知的C.java.php等没有什么本质的区别,也是 ...
- python学习之路------你想要的都在这里了
python学习之路------你想要的都在这里了 (根据自己的学习进度后期不断更新哟!!!) 一.python基础 1.python基础--python基本知识.七大数据类型等 2.python基础 ...
- Python学习之路-Day2-Python基础2
Python学习之路第二天 学习内容: 1.模块初识 2.pyc是什么 3.python数据类型 4.数据运算 5.bytes/str之别 6.列表 7.元组 8.字典 9.字符串常用操作 1.模块初 ...
- Python学习之路-Day1-Python基础
学习python的过程: 在茫茫的编程语言中我选择了python,因为感觉python很强大,能用到很多领域.我自己也学过一些编程语言,比如:C,java,php,html,css等.但是我感觉自己都 ...
- python学习之路网络编程篇(第四篇)
python学习之路网络编程篇(第四篇) 内容待补充
- python 学习之路开始了
python 学习之路开始了.....记录点点滴滴....
- python学习之路,2018.8.9
python学习之路,2018.8.9, 学习是一个长期坚持的过程,加油吧,少年!
随机推荐
- jQuery可拖拽旋转的3D图片墙
在线演示 本地下载
- The minimal unique substring CodeForces - 1159D (构造)
核心观察是形如01,001,0001,...的串循环时, $n$每增长1, $k$就增长1. #include <iostream> #include <sstream> #i ...
- 最新省市区地区数据sql版本(2019年1月)
版本 统计标准2017版 来源 http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/ 建表 CREATE TABLE `area` ( `id` varc ...
- hbase启动后HMaster几秒后死掉
通过 http://s128:16010 无法访问Hbase Web端 查看master日志,有报错: 2019-08-30 16:27:35,137 ERROR [master/s128:16000 ...
- groovy程序设计
/********* * groovy中Object类型存在隐式转换 可以不必使用as强转 */ Object munber = 9.343444 def number1 = 2 println mu ...
- deep_learning_Function_numpy.linspace()
numpy.linspace()等差数列函数 在numpy中的linspace()函数类似与arange().range()函数: arange() .range() 可以通过指定开始值.终值和步长创 ...
- 爬虫之如何找js入口(一)
目标网页:https://m.gojoy.cn/pages/login/ 将我删除i ndex?from=%2Fpages%2Fuser%2Findex 需要工具:chrome和油猴 油猴代码: // ...
- linux工具之pmap
1.pmap简介 pmap命令用来报告一个进程或多个进程的内存映射.可以使用这个工具确定系统是如何为服务器上的进程分配内存的. 例如查看ssh进程的内存映射:
- c# HttpClient和HttpWebRequest添加Basic类型的Authentication认证
c#项目中用到调用客户接口,basic身份认证,base64格式加密(用户名:密码)贴上代码以备后用 1.使用HttpClient实现basic身份认证 using (HttpClient clien ...
- 小程序UI设计(6)-布局分解-九宫格
今天我们来个庖丁解牛.对于一个完整的组合组件,看看通过工具是如何轻松完成的.首先看看九宫格完整的样子. 结构树是这样的.在结构树中,我们可以看到WViewColumn下面有九个WViewRow.WVi ...