python迭代器
python中会使用内存的数据结构有:list、dict、set、str。
比如我们把大量数据存进了list,然后遍历这个list进行读取的话,就会占据大量内存,因此有了迭代器,用来节省空间。
那么如何创建一个python的迭代器呢?
只需要创建一个类,并实现他的__iter__()
、__next__()
方法即可。
__iter__()
:是为了说明这个类是一个迭代器;
__next__()
:是为了在迭代过程中取数据;
举例
class Personal_Iterator:
def __init__(self, data):
self.data = data
def __iter__(self):
return self
def __next__(self):
print("data: ", self.data)
if self.data == 1:
self.data += 1
return self.data
self.data += 1
return self.data
p_iter = Personal_Iterator(1)
print("p_iter", p_iter)
for i in p_iter:
if i >= 10:
break
print("i: ", i)
执行结果:
我们可以尝试一下去掉__iter__()
方法:
可以看到错误显示这个Personal_Iterator对象是不可迭代的,原因就是因为没实现__iter__()
方法,而我们又在使用for循环尝试迭代他,因此产生了错误。
再恢复__iter__()
方法,去掉__next__()
方法尝试看看:
上面说iter()返回了一个不可迭代的类型 ‘Personal_Iterator’,iter()就是我们实现的__iter__()
。为什么会报这个错呢,原因就是在for循环迭代这个对象的时候,会先调用__iter__()
方法,然后返回了一个Personal_Iterator对象,之后再调用它的__next__()
方法,但此时没有实现__next__()
方法,因此报错。
所以总结一下就是,在用for循环遍历某个对象时,会先调用__iter__()
方法,只要有这个方法,那就说明这是个可迭代对象(即迭代器),然后再调用这个迭代器的__next__()
方法,去获取元素。
python生成器
由yield语句替换return语句的函数便是生成器,生成器是一种特殊的迭代器,为什么这么说呢?因为生成器也实现了__iter__()
和__next__()
方法。
举例
def personal_generator(data):
for i in range(5):
data += 1
print("data before yield: ", data)
yield data
print("next iterate")
print("data after yield: ", data)
p_gen = personal_generator(0)
print("p_gen: ", p_gen)
for i in p_gen:
print("i: ", i)
执行结果:
从结果上可以发现,生成器的执行流程是:
- 用 for 循环遍历生成器
- 第一次取出生成器生成的元素时,才会第一次执行函数里的代码,直到
yield data
; - 之后每次迭代都是从
yield
之后的代码开始执行,直到下一次yield
为止; - 一直到函数内的代码全部执行完必,迭代结束;
- 第一次取出生成器生成的元素时,才会第一次执行函数里的代码,直到
解释一下,每次循环实际上会每次对其调用 next()
方法 ,然后生成器执行其函数内的代码,直到 yield
时停止,下一次循环再对生成器调用 next()
方法,然后生成器继续从 yield
后的代码执行,直到下一个 yield
停止。
总结
- 迭代器
- 实现了
__iter__()
、__next__()
方法的对象;
- 实现了
- 生成器
- 特殊的迭代器;
- 区别
- 一个需要手动实现
__iter__()
、__next__()
方法,而另一个只需要通过yield
关键字即可生成;
- 一个需要手动实现
参考: