概述
目录
- 1.为什么要有迭代器?
- 2.迭代器的工作原理
- 2.1.可迭代对象
- 2.1.1. 什么是迭代对象?
- 2.1.2. 可迭代对象有什么用?
- 2.2.for循环与迭代器
- 3.生成器的工作原理
1.为什么要有迭代器?
列表所有数据都在内存中,如果有海量数据的话将会非常耗内存。
仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
那怎么做到只访问一两个元素,而不加载全部元素呢?迭代器可以做到。
例1(感受一下迭代器的作用)
t = [x * x for x in range(10)]
L = []
count = 0
g = iter(t)
while len(L) <= 10 :
try:
item = next(g)
count += 1
print(f'调用next()第{count}次获得的值为:{item}')
L.append(item)
except StopIteration:
print('n迭代完成n')
break
print(L,'n')
调用next()第1次获得的值为:0
调用next()第2次获得的值为:1
调用next()第3次获得的值为:4
调用next()第4次获得的值为:9
调用next()第5次获得的值为:16
调用next()第6次获得的值为:25
调用next()第7次获得的值为:36
调用next()第8次获得的值为:49
调用next()第9次获得的值为:64
调用next()第10次获得的值为:81
迭代完成
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
对于上面的列表 t ,往往每次只需要处理其中的一个元素。
如果不进行迭代处理,每次处理就需要把整个列表计算出来并加载到内存中来,而每次仅处理一个元素,这样是非常消耗内存。
况且这里的列表 t 还很小,假设这个列表变得有有成千上万上亿的元素,每次加载到内存,会占很大的内存空间,但是每次还是只处理一个元素,这样的内存消耗是非常巨大的
而进行了迭代处理,我并不需要每次都把整个列表 t 计算并加载出来,我只需要每次需要元素的时候,再计算那个元素,比如我需要第一个元素,计算出来加载到内存中,其他的元素则无需管。——每次只加载一个元素到内存,内存消耗会小很多。
总之:迭代器在循环处理大量数据的时候,能够减少非常多不必要的内存消耗。
2.迭代器的工作原理
说到迭代器又不得不说说可迭代对象
先一个一个捋清楚
2.1.可迭代对象
2.1.1. 什么是迭代对象?
就是可以迭代的对象,迭代就是每次只一次访问一个值,下次再访问下一个值。
可迭代对象有:字符串、列表、元组、字典、集合等等。
凡是可以for循环的对象都是可迭代对象,如列表的迭代,用for循环,每次获取list的一个值,下次获取下一个值。
例2
List = [1,2,3,4,5]
count = 0
for item in List:
count = count + 1
print(f'第{count}次获取的值:{item}')
第1次获取的值:1
第2次获取的值:2
第3次获取的值:3
第4次获取的值:4
第5次获取的值:5
2.1.2. 可迭代对象有什么用?
每个可迭代对象内置方法有:__iter__()、__next__()。
-
__next__()方法:
此方法是可迭器能够迭代的关键,每次调用__next__()可以获取下一个值,然后停下来,再次调用又可以获取下一个值,直到__next__()抛出 StopIteration 异常,这个异常表示迭代完成。但是能够调用此方法的前提是:可迭代对象变成了迭代器,仅仅是迭代对象是不能调用此方法的(不能迭代)。那怎么把迭代对象变成迭代器呢? -
__iter__()方法:
作用于可迭代对象后,返回一个迭代器,只有迭代器才能真正进行迭代(才能进行调用__next__()方法)
可迭代对象调用了__iter__()方法就可以迭代器
可迭代对象的__iter__()方法由python的内置函数iter()调用
可迭代对象的 __next__()方法由python内置函数next()调用
总的来说:迭代器由可迭代对象而来,迭代器能够进行迭代,可迭代对象则不能。
例3(可迭代对象没有变成迭代器进行迭代)✘
List = [1,2,3,4,5] # 一个可迭代对象list
print(next(List))
TypeError: 'list' object is not an iterator
例4(可迭代对象转成迭代器进行迭代)✔
List = [1,2,3,4,5]
li = iter(List)
print(next(li))
print(next(li))
print(next(li))
print(next(li))
print(next(li))
1
2
3
4
5
2.2.for循环与迭代器
for循环本质上就是将可迭代对象转成迭代器,每一次循环调用一次 next(),直到捕获到 StopIteration 异常,停止循环。
例5(与例1如出一撤,这里用for实现)
t = [x * x for x in range(10)]
count = 0
L = []
for item in t:
count += 1
print(f'调用next()第{count}次获得的值为:{item}')
L.append(item)
调用next()第1次获得的值为:0
调用next()第2次获得的值为:1
调用next()第3次获得的值为:4
调用next()第4次获得的值为:9
调用next()第5次获得的值为:16
调用next()第6次获得的值为:25
调用next()第7次获得的值为:36
调用next()第8次获得的值为:49
调用next()第9次获得的值为:64
调用next()第10次获得的值为:81
迭代完成
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
for循环其实就是迭代器的使用,只不过for循环方便了我们使用迭代器,省去了很多代码。
3.生成器的工作原理
生成器本质上就是一个迭代器,可以利用next()进行迭代。只不过这个迭代器的对象是一个函数(大部分都是)。
生成器是迭代器的一个应用,是函数的一种形式,使用了 yield 的函数被称为生成器(generator)。
yield可以返回一个或多个值,并记住当前位置。 其实就是替代了原来的return,return执行过后会重新来过,不标记任何位置,每次都全部执行一遍然后返回一个或多个值。
每次调用生成器,yield会返回一个指定值(或不返回),并标记当前位置。下次再调用它时,从yield标记的位置开始执行。直到抛出 StopIteration 停止迭代。
这样做的好处也是减少不必要的内存损耗,因为有些场景不需要每次调用函数都把循环内容重新过一遍。
例6(用next()迭代)
A = 1
B = 1
C = 0
def ADD(): # 生成器
for _ in range(3):
global A, B, C
i = A + B
C += i
yield C
return C
f = ADD()
while True:
try:
print (next(f))
except StopIteration:
print('n迭代完成')
break
2
4
6
迭代完成
例7(用for迭代)
A = 1
B = 1
C = 0
def ADD(): # 生成器
for _ in range(3):
global A, B, C
i = A + B
C += i
yield C
return C
f = ADD()
for item in f:
print(item)
print('n迭代完成n')
2
4
6
迭代完成
最后
以上就是天真云朵为你收集整理的彻底理解 Python 迭代器与生成器1.为什么要有迭代器?2.迭代器的工作原理3.生成器的工作原理的全部内容,希望文章能够帮你解决彻底理解 Python 迭代器与生成器1.为什么要有迭代器?2.迭代器的工作原理3.生成器的工作原理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复