20190220 可迭代对象、迭代器、生成器
可迭代对象、迭代器、生成器
说明
-
可迭代对象包含迭代器。
-
如果一个对象拥有__iter__方法,是可迭代对象(类似接口);如果一个对象拥有__next__方法,是迭代器(类似接口的实现类)。
-
定义可迭代对象,必须实现__iter__方法;定义迭代器,必须实现__iter__和__next__方法。
-
具有yield关键字的函数都是生成器。
自定义一个迭代器
class MyIterable:
def __iter__(self):
return self
def __init__(self, lst):
self.lst = lst
self.index = 0
def __next__(self):
try:
ret = self.lst[self.index]
self.index += 1
except IndexError:
raise StopIteration
return ret
if __name__ == '__main__':
li = MyIterable([1, 2, 3, 5])
for i in li:
print(i)
自定义一个生成器和一个普通函数的区别
# 一个普通的函数
def fun():
return 1 # return关键字在这里只能定义一个
# 只要函数中有yield关键字就是生成器
def gen_fun():
yield 1
yield 2
yield 3 # 但是yield和return不同可以定义多个
if __name__ == '__main__':
# python编译字节码的时候,会根据yield关键字认定这个函数是生成器。
# 然把这个函数转换成一个生成器,这个过程完全是python帮助我们进行的。
gen = gen_fun() # <generator object gen_fun at 0x03C7DC30>
ret = fun() # 1
# gen_fun()执行,返回了生成器对象
# fun()执行,返回了1
# 遍历生成器
for v in gen:
print(v) # 1 2 3
使用生成器写一个斐波那契额数列函数
# 使用生成器技术写一个斐波那契数列函数
def gen_fib(index):
n, a, b = 0, 0, 1
while index > n:
yield b
a, b = b, a + b
n += 1
if __name__ == '__main__':
for i in gen_fib(1000000): # 每一位的数据都是动态生成的,非常节省内存资源
print(i)
使用生成器读写大文件
def read_file(fp, spl_str):
"""
读取大文件
:param fp: 文件读写句柄
:param spl_str: 每一行的分隔符
"""
str_buf = ''
spl_len = len(spl_str)
while 1:
# 缓存中找分隔符
while spl_str in str_buf:
# 找到分隔符位置,用来切片字符串
index = str_buf.index(spl_str)
# yield出切片后的字符串
yield str_buf[:index]
# 将分隔符后面的有效字符串缓存
str_buf = str_buf[index + spl_len:]
# 读取信息
chunk = fp.read(4096 * 10)
# 处理读到数据
if chunk:
str_buf += chunk
# 处理剩余数据
else:
yield str_buf
break
if __name__ == '__main__':
with open('data', 'r') as file:
for con in read_file(file, '{|}'):
print(con)