python_学习笔记0825
2015-08-25 22:55
525 查看
今天是二零一伍年八月二十五日
1、在python中有像list、tuple这样的对象,他们是可迭代的(Iterable),这样的对象在for语句中被循环。但是我们都知道,list是一个有限的对象。也就是说,其实当list被创建以后,他是具有长度的,每一个元素在内存中都是有位置的。但是有时候,在一个list里面,我们有时候只需要前面几个元素,这样就造成了大量内存浪费。为了防止这种浪费,我们就需要一种新的数据类型——生成器(generator)
顾名思义,生成器是动态生成内容的,比如:
把原来的方括号修改为圆括号,就是我们的生成器了。g的列举更加灵活:
next()语句帮助我们一步一步的“计算”生成器中的值。生成器中保留的其实是一种算法和计数器,每次使用next时,就计算下一个元素的值。当然,在我们的算法里也有一个上限,所以我们在访问到最后就会有StopIteration的异常被抛出。当然我们的生成器也可以像其他可迭代对象一样被for循环直接输出。
但是有时候,生成一个有逻辑的序列却并不是那么简单。比如斐波那契数列,我们们能仅仅用列表生成器就生成吗?不行,这个时候必须使用函数:
那么我们能用生成器生成一个动态斐波拉切吗,答案是可以的。那么我们就来分析一下斐波拉切函数,在这个函数里,我们真正需要的其实是b这个变量,而print这个函数正好是输出了这个变量。所以,想要把这个函数变成生成器,我们要从这里入手,我们只用把打印语句改成yield b就行,也就是这样:
这个时候我们再尝试去使用这个函数的时候就不一样了。
此时的g就是一个生成器了,我们使用next或者是for循环就能打印出我们的斐波拉切数列。但是我们看回我们的定义,发现我们还有一个done被return了,那么它到底什么时候被返回呢?这个我想大家不用想也知道,它会在我们原先被抛出异常的时候返回,也就是:
当然要是我们想正常输出这个done的话,我们就需要捕获异常了
2、刚刚在使用生成器的时候使用了Next句柄,那么,是否还有其他的对象也可以使用next?答案是当然的,这样的对象我们统一称为——迭代器(Iterator)。那么我们的list、string是迭代器吗?答案是否定的,关于这一点我们可以使用isinstance函数去检验。他们只是可迭代的(Iterable),远不是迭代器。不过没有关系我们可以使用iter()函数使它变成迭代器。
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
那么为什么我们所钟爱的这些数据类型不能成为迭代器呢?因为我们所称的迭代器往往是一个数据流,它往往需要next函数去一个一个计算下一个值。有时候我们称迭代器是惰性的,只有当我们需要下一个数据的时候他才会计算。
1、在python中有像list、tuple这样的对象,他们是可迭代的(Iterable),这样的对象在for语句中被循环。但是我们都知道,list是一个有限的对象。也就是说,其实当list被创建以后,他是具有长度的,每一个元素在内存中都是有位置的。但是有时候,在一个list里面,我们有时候只需要前面几个元素,这样就造成了大量内存浪费。为了防止这种浪费,我们就需要一种新的数据类型——生成器(generator)
顾名思义,生成器是动态生成内容的,比如:
l = [x * x for x in range(10)] g = (x *x for x in range(10) )
把原来的方括号修改为圆括号,就是我们的生成器了。g的列举更加灵活:
>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g) 36 >>> next(g) 49 >>> next(g) 64 >>> next(g) 81 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
next()语句帮助我们一步一步的“计算”生成器中的值。生成器中保留的其实是一种算法和计数器,每次使用next时,就计算下一个元素的值。当然,在我们的算法里也有一个上限,所以我们在访问到最后就会有StopIteration的异常被抛出。当然我们的生成器也可以像其他可迭代对象一样被for循环直接输出。
但是有时候,生成一个有逻辑的序列却并不是那么简单。比如斐波那契数列,我们们能仅仅用列表生成器就生成吗?不行,这个时候必须使用函数:
# generator.py def fib(max): n , a , b = 0 , 0 , 1 while n < max : print(b) a , b = b , a + b n += 1 return 'done'
那么我们能用生成器生成一个动态斐波拉切吗,答案是可以的。那么我们就来分析一下斐波拉切函数,在这个函数里,我们真正需要的其实是b这个变量,而print这个函数正好是输出了这个变量。所以,想要把这个函数变成生成器,我们要从这里入手,我们只用把打印语句改成yield b就行,也就是这样:
# generator.py def fib(max): n , a , b = 0 , 0 , 1 while n < max : yield b a , b = b , a + b n += 1 return 'done'
这个时候我们再尝试去使用这个函数的时候就不一样了。
g = fib(6)
此时的g就是一个生成器了,我们使用next或者是for循环就能打印出我们的斐波拉切数列。但是我们看回我们的定义,发现我们还有一个done被return了,那么它到底什么时候被返回呢?这个我想大家不用想也知道,它会在我们原先被抛出异常的时候返回,也就是:
Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration: done
当然要是我们想正常输出这个done的话,我们就需要捕获异常了
2、刚刚在使用生成器的时候使用了Next句柄,那么,是否还有其他的对象也可以使用next?答案是当然的,这样的对象我们统一称为——迭代器(Iterator)。那么我们的list、string是迭代器吗?答案是否定的,关于这一点我们可以使用isinstance函数去检验。他们只是可迭代的(Iterable),远不是迭代器。不过没有关系我们可以使用iter()函数使它变成迭代器。
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
那么为什么我们所钟爱的这些数据类型不能成为迭代器呢?因为我们所称的迭代器往往是一个数据流,它往往需要next函数去一个一个计算下一个值。有时候我们称迭代器是惰性的,只有当我们需要下一个数据的时候他才会计算。
相关文章推荐
- Python动态类型的学习---引用的理解
- Python3写爬虫(四)多线程实现数据爬取
- 垃圾邮件过滤器 python简单实现
- 下载并遍历 names.txt 文件,输出长度最长的回文人名。
- install and upgrade scrapy
- Scrapy的架构介绍
- Centos6 编译安装Python
- 使用Python生成Excel格式的图片
- 让Python文件也可以当bat文件运行
- [Python]推算数独
- Python中zip()函数用法举例
- Python中map()函数浅析
- Python将excel导入到mysql中
- Python在CAM软件Genesis2000中的应用
- 使用Shiboken为C++和Qt库创建Python绑定
- FREEBASIC 编译可被python调用的dll函数示例
- Python 七步捉虫法