迭代器、生成器

       迭代器和生成器并不像一般的数据结构一样把所有的对象一次性加载在内存中,而是以延迟计算的方式在调用时逐次生成。

1.迭代器(next)

*可迭代对象Iterable

       可以通过for循环遍历其中元素的对象是可迭代对象(必须有__iter__方法): 可以返回一个迭代器的对象称为可迭代对象,实现了__iter__()方法,通过调用iter()方法可以获得一个迭代器,列表、字典、元组、集合、字符串、打开的文件、迭代器是可迭代对象,故可用于for循环。【库collections中的iterable方法可以判断是否为可迭代对象】

*迭代器Iterator

       可以通过next访问取值的对象为迭代器(必须有__iter__和__next__方法):可以实现__iter__和__next__方法的对象是迭代器__iter__()返回迭代器自身__next__()返回容器中的下一个值,__iter__()执行一次,__next__()执行多次,通过每次调用next()方法来实现取值,当所有元素都被返回后,再执行next()会抛出StopIteration异常。 【库collections中的iterator方法可以判断是否为迭代器】

#列表、元组、字典、字符串等可通过iter()函数转为迭代器,从而用next()方法获取各元素的值
ls = [2, 4, 6]           #是可迭代对象
ls_iter = iter(ls)       #用iter()函数转为迭代器
print(next(ls_iter))     #用next()方法取值,得2
print(next(ls_iter))     #得4
print(next(ls_iter))     #得6
print(next(ls_iter))     #引发StopIteration异常,迭代完成
  
 为了让迭代器和循环相兼容,会有一个捕获停止迭代的异常,即迭代完后抛出raise StopIteration异常

       优点-->迭代器同一时刻在内存中只有一个值,可以存放无限大的数据流

       缺点-->从前向后,不能倒退,除非取尽否则无法获取长度

2.生成器(yield)

       生成器是一个特殊的函数,用于每次调用时生成一个值。碰到yield关键字暂停执行后续代码并返回一个值,通过yield关键字一次次生成,可以从上一次终止的位置往下继续生成。生成器是特殊的迭代器,自动实现了迭代器的__iter__和__next__方法,可以通过循环去遍历,生成器一定是迭代器,也是可迭代对象。

        yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而 yield可以保存函数的运行状态,挂起函数,用来返回多次值。

           python提供的常用的生成器函数:
1.enumerate(iterable, start = 0): 
     得一个个元组(index, item),index从start开始,item从iterable中取
2.map(func, [it1, it2, ...,itn]):将it中各个元素传入func后输出
     eg: list(map(int, input()))

            生成器表达式是列表推导式的生成器版本:
列表--》   x = [x * x for x in range(10)]
生成器--》 x = (x * x for x in range(10))

运行结果:

3.生成器和迭代器的关系

       生成器函数或者生成器表达式是生成器

       生成器一定是迭代器(通过next取值)

       迭代器一定是可迭代对象,可迭代对象通过__iter__()方法可以生成一个迭代器

eg

list_data = [1, 2, 3, 4, 5]

for num in list_data:       #本质上列表这个可迭代对象调用__iter__方法生成一个迭代器,然后循环 

        print(num)            # 调用迭代器的__next__方法取值

等价的:

list_data = [1, 2, 3, 4, 5]
i=iter(list_data)                 #每次都需要重新获取一个迭代器对象
while True:
    try:
        print(next(i))
    except StopIteration:    #捕捉异常终止循环
        break

4.应用:

*获取前 n 个自然数(利用yield可以避免n很大时内存吃不消)

def first_n(n):

        num= 0

        while num < n:

                yield(num)

                num += 1

print(first_n(10000000))

*惰性加载--流式读取

流式读取是通过构造生成器逐块读取、处理大文件的方法:比如文件有16G,而电脑内存只有4G

若为文本文件,可以逐行读取:

with open ('wenjianweizhi') as f

for line in f:

        print(line)

若非文本文件,则需构造生成器:

def read_big_file(file, size = 1024):

        while True:

                read_data = fole.read(size)

                if not read_data:

                        break

               else:

                        yield read_data
f = open('wenjianweizhi')
for read_data in read_big_file(f):
    process_data(read_data)

       备:with open 和 open的区别-->用open打开文件,必须使用close关闭;用with open 打开文件,可以不用close关闭,即使运行中遇到问题都可以自动安全退出并给出报错信息。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值