6、Python之迭代器&生成器

迭代器

1.什么是迭代器?

迭代是重复的活动, 而每一次迭代得到的结果会作为下一次迭代的初始值,单纯的重复并不是迭代 。

迭代器即用来迭代取值的工具 。

2.为什么要使用迭代器?

把多个值循环取值出来的类型有:字符串 列表 元组 字典 集合 打开文件,而上述取值方式只适用于有索引的数据类型,列表,字符串,元组。而Python必须提供一种不依赖于索引的取值方式,就是迭代器

3.什么是可迭代对象?

但凡内置有__ iter __方法的都称之为可迭代对象

以下类型都可

# s1=''
# # s1.__iter__()
#
# l=[]
# # l.__iter__()
#
# t=(1,)
# # t.__iter__()
#
# d={'a':1}
# # d.__iter__()
#
# set1={1,2,3}
# # set1.__iter__()
#
# with open('a.txt',mode='w') as f:
#     # f.__iter__()
#     pass

案例:迭代器与while循环

d={'k1':1,'k2':2,'k3':3}
d_iterator=d.__iter__()  # 会将其转换成迭代器对象
# print(d_iterator) # 内存地址
# print(d_iterator.__next__()) # 会取到key值
# print(d_iterator.__next__())
# print(d_iterator.__next__())
# print(d_iterator.__next__()) # 会抛出异常 StopIteration  只有三个值可打印

# while True:
#     print(d_iterator.__next__())   # 仍然会抛出异常,会一直循环,没有结束的条件

# 对同一个迭代器取值,在取干净的情况下,在对其取值,取不到值
while True:
    try:
        print(d_iterator.__next__())
    except StopIteration:
        break

# 如果想在取一遍值,需要重新对其迭代  d_iterator=d.__iter__()

案例:迭代器与for循环

# 可迭代对象补充知识
# 可迭代对象:可以转换为迭代器的对象
# 迭代器对象:内置有__next__方法,并且内置有__iter__方法的对象
# 迭代器对象.__next__():会得到迭代器的下一个值
# 迭代器对象.__iter__():得到迭代器本身   # for循环更好的与迭代器运行

# foe循环的工作原理
# 1.调用__iter__()得到一个迭代器对象
# 2.迭代器对象.__next__()拿到一个返回值,然后将该返回值赋给k
# 3.循环往复步骤2,直到抛出异常,for循环会捕捉异常


d={'k1':1,'k2':2,'k3':3}
for k in d:
    print(k)

可迭代对象:字符串,列表,元组,字典,集合,文件对象

迭代器对象:文件对象

注意:打开文件既是可迭代对象又是迭代器对象

迭代器优缺点:

优点:

1.为序列和非序列类型提供了一种统一的迭代取值方式

2.惰性计算:迭代器对象表示的是一个数据流,在需要时才去调用next来计算出一个值,就迭代器本身来说,同一时刻在内存中只有一个值,因而可以存放无限大的数据流,而对于其他容器类型,如列表,需要把所有的元素都存放于内存中,受内存大小的限制,可以存放的值的个数是有限的。

缺点:

1、除非取尽,否则无法获取迭代器的长度

2、只能取下一个值,不能回到开始, 若是要再次迭代同个对象,只能重新调用iter方法去创建一个新的迭代器对象

生成器

1.什么叫生成器

生成器就是迭代器,自定义的迭代器

2.如何得到自定义的生成器

在函数内一旦存在yield关键字,调用函数并不会执函数体代码,会返回一个生成器对象,生成器既自定义的迭代器

def func():
    print('第一次')
    yield 1
    print('第二次')
    yield 2
    print('第三次')
    yield 3

g = func()
# print(res)
# 会触发函数体代码的运行,然后遇到yield停下来,将yield后面的值当做本次调用的结果打印
res1=g.__next__()
print(res1)
res2=g.__next__()
print(res2)
res3=g.__next__()
print(res3)
# 没有返回值了就会报错,抛出异常

应用案例:

def my_range(start,stop,step=1):
    while start < stop:
        yield start
        start+=step

g=my_range(1,5,2)
print(next(g)) # next(g)=g.__next__()
print(next(g))

yield的表达方式1:

def func(name):
    print('我是%s' %name)
    while True:
        x=yield # x拿到的是yield接收的值
        print('我是%s,我今年%s' %(name,x))

g=func('andy')
g.send(None) # 等于next(g) 第一次必须传None,负责会抛出异常

g.send('12')
g.close()# 关闭后无法传值

yield表达方式2:

def func(name):
    hobby_list=[]
    print('我是%s' %name)
    while True:
        x=yield hobby_list
        print('我是%s,我喜欢%s' %(name,x))
        hobby_list.append(x)

g=func('andy')
g.send(None) # 等于next(g) 第一次必须传None,负责会抛出异常

g.send('追剧')
# g.close()# 关闭后无法传值

res=g.send('跑步')
print(res) # 打印列表['追剧', '跑步']

posted on 2022-07-05 18:02  AprilX  阅读(48)  评论(0)    收藏  举报