Python知识——迭代器、生成器

迭代器

什么是迭代器
迭代器指的是迭代取值的工具,迭代是一个重复的过程,每次重复都是基于上一次结果而继续的,单纯的重复并不是迭代

count = 0
while count < 5:
	print(count)
	count += 1

为何要有迭代器
迭代器是用来取值的工具,而涉及到把多个值取出来的类型有:列表,字符串,元组,字典,集合,文件。

以下是一个用while循环取值的案例:

l = ['张三', '李四', '王五']
i = 0
while i < len(l):
    print(l[i])
    i += 1

'''
张三
李四
王五
'''

上述迭代取值的方法只适用于有索引的数据类型:列表、字符串、元组
所以上述索引取值具有局限性
python必须提供一种能够不依赖索引的取值方式,这就是迭代器

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

s1 = ''
s1.__iter__()

l = []
l.__iter__()

t = (1,)
t.__iter__()

d = {'a': 1}
d.__iter__()

set1 = {1, 2, 3}
set1.__iter__()

with open(r'D:\a.txt',mode='w') as f:
    f.__iter__()

调用可迭代对象下的__iter__方法会将其转换成迭代器对象

d = {'a': 1}
ret=d.__iter__()
print(ret)

'''
<dict_keyiterator object at 0x00000292E33CDB30>
'''

将可迭代对象转换为迭代对象后,可进行取值,这种方法不依赖索引,就可以取值

d = {'a': 1,'b':2,'c':3}
ret=d.__iter__()
print(ret)
print(ret.__next__())
print(ret.__next__())
print(ret.__next__())

'''
<dict_keyiterator object at 0x000002BB6185DB30>
a
b
c
'''

加上while循环:

d = {'a': 1,'b':2,'c':3}
ret=d.__iter__()
while True:
	print(ret.__next__())
'''
a
b
c
Traceback (most recent call last):
  File "d:\python\study_6_19.py", line 16, in <module>
    print(ret.__next__())
StopIteration
'''

但是会有报错,这时需要一些没有学过的知识去掉报错

d = {'a': 1,'b':2,'c':3}
ret=d.__iter__()
while True:
    try:
        print(ret.__next__())
    except StopIteration:
        break
'''
a
b
c
'''

遇到报错信息时,就跳出循环

上述的方法虽然可以解决不用索引取值,但是需要先将可迭代对象转换成迭代器对象,在使用__next__方法取值,还需要自行捕捉异常,非常麻烦

一个for循环即可解决问题:

d = {'a': 1,'b':2,'c':3}
for k in d:
    print(k)

'''
a
b
c
'''

for循环的工作原理:

1、d.__iter__()得到一个迭代器对象
2、迭代器对象.__next__()拿到一个返回值,然后该返回值赋值给k
3、循环往复步骤2,知道抛出StopIteration 异常  for循环会捕捉异常然后结束循环

迭代器优缺点总结
优点:

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

缺点:

  1. 除非取尽、否则无法获取迭代器的长度
  2. 只能取下一个值,不能回到开始,更像是“一次性的”,迭代器产生后的唯一目标就是重复执行next方法直到值取尽,否则就会停在某个位置,等待下一次调用next;若是再次迭代同个对象,只能重新调用iter方法取创建一个新的迭代器对象,如果有两个或者多个循环使用同一个迭代器,必然只会有一个循环能取到值。

生成器

在上述的迭代器中,都是运用了已经给好的列表、字典、元组等等,如果有一需求,就是要迭代上千万个值,难道就是先定义个拥有上千万个值的列表吗?内存警告!
所以就需要一个能够产生上千万个值的方法

关键字:yield

带有 yield 的函数在 Python 中被称之为 generator(生成器),何谓 generator ?
看一下代码:

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

func()

'''

'''

可以发现,调用func函数的时候,并没有产生任何结果,也就是说函数并没有运行
查看一下func()的返回值

g=func()
'''
<generator object func at 0x000001A07E0D9510>
'''
g.__iter__()
print(g.__next__())
#说明生成器就是迭代器,并且此时函数执行了代码
#触发函数体代码的运行,然后遇到yield停下来,将yield后的值当做当做本次调用的结果返回

'''
第一次
1
'''

此时产生了一个generator(生成器),并且此时发现生成器也有内置的iter,next方法,所以可知生成器其实就是迭代器

生成器运用

def my_range(start, stop, stpe=1):
    print('start')
    while start < stop:
        yield start
        start += stpe
    print('end')


for n in my_range(1,7,2): #第一个参数是起始位置,第二个参数是最终位置,第三个是步长
    print(n)
  1. 首先执行for循环,for循环会进行my_range( ).__iter__操作,再进行my_range( ).__next__
  2. 此时函数会返回一个返回值,这个返回值是生成器运行到yield时返回的1
  3. 函数内部回继续运行代码到下一个yield,就会停止,直到for循环再次进行操作,得到返回值
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值