列表生成式,迭代器&生成器

       列表生成式




 


[1, 2, 3, 4, 5, 6, 7, 8, 9],把列表里的每个值乘2

第一种方法

a = [1,2,3,4,5,6,7,8,9]

for index,i in enumerate(a):
a[index] *=2
print(a)
第三种
a = [1,2,3,4,5,6,7,8,9]

a = map(lambda x:x*2, a)
<map object at 0x101d2c630>
 for i in a:print(i)

第四种
a = [1,2,3,4,5,6,7,8,9]
a = [i*2 for i in range(10)] >>>[2,4,6,8,10,12,14,16,18]
这就叫做列表生成

 



生成器

 


通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含上亿个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。


要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
a = (x*2 for x in range(10))
a就是一个生成器对象 且可迭代
<generator object foo at 0x0000016D83F16A40>
打印出generator的每一个元素 如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值
next(a)>>2
next(a)>>4
next(a)>>6
next(a)>>8
next(a)>>10
next(a)>>12
next(a)>>14
next(a)>>16
next(a)>>18
generator保存的是算法,每次调用next(a),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

正确的方法是使用for循环,因为generator也是可迭代对象:
a = (x*2 for x in range(10)
for i in a:
print(i)
我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

def fib(max):
    n ,before,after = 0,0,1
while n<max:
print(before)
before,after = after ,before+after
n+=1

fib(10)
上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:

def fib(max):
n ,before,after = 0,0,1
while n<max:
# print(before)
yield before #生成器next方法
before,after = after ,before+after
n+=1

# fib(10)
g = fib(8)
print(g)
print(next(g))
for i in g:
print(i)

迭代器

 每一个生成器都是迭代器 迭代器不一定是生成器
以直接作用于for循环的数据类型有以下几种:

一类是集合数据类型,如listtupledictsetstr等;

一类是generator,包括生成器和带yield的generator function。

这些可以直接作用于for循环的对象统称为可迭代对象:Iterable

有iter()方法和next()方法才叫迭代器

for  i in [1,3,4,5]

for循环内部三件事:

调用可迭代对象的iter方法返回一个迭代器
不断调用迭代器next方法
处理StopIteration错误


可以使用isinstance()判断一个对象是否是Iterable对象:
from collections import Iterable,Iterator
b = [1,2,3,4]
a = isinstance(b,list)

print(a)
b =iter(b)
print(isinstance(b,Iterator))

>>TRUE  TRUE

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

 
 
 
 
 
 

 
 

 

posted @ 2017-10-22 20:23  年轻人的魄力  阅读(188)  评论(1编辑  收藏  举报