迭代协议一共有两个类型,一种是Iterable(可迭代),另一个是迭代器Iterator。两者的类型不同。
from collections.abc import Iterable,Iterator
a = [1,2]
iter_rator = iter(a)
print(isinstance(iter_rator,Iterator))
生成器原理
生成器函数的使用,只要有yield关键字就是生成器函数。
gen = gen_func()通过这样的方式,gen获得一个生成器对象。
#生成器函数,函数里只要有yield关键字
def gen_func():
yield 1
yield 2
yield 3
def fib(index):
if index <= 2:
return 1
else:
return fib(index-1) + fib(index-2)
def fib2(index):
re_list = []
n,a,b = 0,0,1
while n<index:
re_list.append(b)
a,b = b, a+b
n += 1
return re_list
def gen_fib(index):
n,a,b = 0,0,1
while n<index:
yield b
a,b = b, a+b
n += 1
for data in gen_fib(10):
print (data)
# print (gen_fib(10))
# 斐波拉契 0 1 1 2 3 5 8
#惰性求值, 延迟求值提供了可能
def func():
return 1
if __name__ == "__main__":
#生成器对象, python编译字节码的时候就产生了,
gen = gen_func()
for value in gen:
print (value)
# re = func()
# pass
python.exe会用一个叫做 PyEval_EvalFramEx(c函数)去执行foo函数, 首先会创建一个栈帧(stack frame)
import inspect
frame = None
def foo():
bar()
def bar():
global frame
frame = inspect.currentframe()
生成器对象的封装
有yield就是生成器典型。
def gen_func():
yield 1
name = "bobby"
yield 2
age = 30
return "imooc"
import dis
gen = gen_func()
print (dis.dis(gen))
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
next(gen)
print(gen.gi_frame.f_lasti)
print(gen.gi_frame.f_locals)
案列:使用生成器表达式
需求:500G的数据,但是在一行上,导致f.readlines()没用。我需要把一行数据,按照分隔符进行逐行打印
#500G, 特殊 一行
def myreadlines(f, newline):
buf = ""
while True:
while newline in buf:
pos = buf.index(newline)
yield buf[:pos]
buf = buf[pos + len(newline):]
chunk = f.read(4096)
if not chunk:
#说明已经读到了文件结尾
yield buf
break
buf += chunk
with open("input.txt") as f:
for line in myreadlines(f, "{|}"):
print (line)