- 迭代器为集合提供了一种访问元素的方式,用来遍历元素
- 迭代器遍历与下标访问不一样,下标访问是返回一个数值,迭代器不返回任何数值,迭代器能够惰性获取元素
迭代协议
- 实现__iter__魔法函数,对象是可迭代的
- 实现__next__、__iter__ ,对象是一个迭代器
自定义迭代器
#自定义迭代器
class MyIter:
def __init__(self, list):
self.index = 0 #内部维护的指针
self.list = list #需要迭代的对象
#每次进行迭代操作,都会调用一次next魔法函数,返回一个结果
def __next__(self):
try:
item = self.list[self.index]
except IndexError: #当访问列表超出范围时,会抛出IndexError 异常
raise StopIteration #抛出异常结束迭代
self.index += 1 #内部指针加一
return item #返回迭代的结果
class Color:
def __init__(self,*args):
self.items = list(args)
def __iter__(self): #当使用 for,iter 对实例进行操作时候,返回一个迭代对象
return MyIter(self.items)
def __getitem__(self, item): # 当没有实现iter时,会进行降级操作,创建一个默认迭代器
return self.items[item]
c = Color('red', 'blue', 'write', 'green', 'yellow', 'pink')
t = iter(c) # 会调用对象的 iter魔法函数,返回一个迭代器
for i in c: # 会调用对象的 iter魔法函数,返回一个迭代器,一直调用迭代器的 next魔法函数,直到抛出 StopIteration异常
print(i)
生成器的使用
# 斐波那契数列 1、1、2、3、5、8、13、21、34
def fid(index):
"""
返回第 index 位的数值
"""
if index <= 2:
return 1
else:
return fid(index-1) + fid(index-2)
def fid2(index):
"""
返回列表表现形式
"""
n, a, b = 1, 1, 1
l = [1]
while n < index:
l.append(b)
a, b = b, a+b
n += 1
return l
def fid3(index):
"""
使用生成器器实现
"""
n, a, b = 1, 1, 1
yield 1
while n < index:
yield b
a, b = b, a+b
n += 1
if __name__ == "__main__":
# 直接调用会返回生成器,而不是数值
f = fid3(5)
print(f)
for i in fid3(2):
print(i)
生成器与函数调用的区别是
- 函数的代码块会完整的执行一遍,遇到return返回结果。下次在调用函数时会重新从代码块的第一行执行。
- 生成器调用时,遇到yield会暂停代码块的执行,返回结果。下次调用生成器,会在上次yield停止的地方继续往下执行。
生成器应用
使用迭代器,读取一个以 | 分割的大文件
import os
def get():
fd = os.open('test.log', os.O_RDONLY)
str_buf = ''
while True:
data = os.read(fd, 33)
if data == bytes('','utf8'):
break
str_buf += str(data, 'utf8')
if '|' in str_buf:
while True:
index = str_buf.find('|')
yield str_buf[:index+1]
str_buf = str_buf[index+1:]
if "|" not in str_buf:
break
if __name__ == '__main__':
for item in get():
print(item)