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

python_学习笔记0825

2015-08-25 22:55 525 查看
今天是二零一伍年八月二十五日

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函数去一个一个计算下一个值。有时候我们称迭代器是惰性的,只有当我们需要下一个数据的时候他才会计算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息