python高级编程------可迭代对象,迭代器
一。迭代 协议,迭代器,可迭代对象 概念
#什么是迭代协议 (可迭代类型Iterable,iterator )
#迭代器是什么? 迭代器是访问集合内元素的一种方式, 一般用来遍历数据
#迭代器和以下标的访问方式不一样, 迭代器是不能返回(反向)的, 迭代器提供了一种惰性方式数据的方式
#[] list , __iter__(迭代协议)
#只要实现__iter__方法就是可迭代对象,但不是迭代器
#Iterator继承Iterable,实现了__iter__,和 __next__(是一个@abstractmethod)
from collections.abc import Iterable, Iterator
a = [1,2]
iter_rator = iter(a)
print (isinstance(a, Iterable)) #判断是否是可迭代的 True
print (isinstance(iter_rator, Iterator)) #判断是否是迭代器 True
print (isinstance(a, Iterator)) #判断是否是迭代器 False
二。自定义迭代器
在实现迭代器的时候,可以继承自Iterator,iterator内部实现了__iter__,我们只需要重写__next__方法就行
当然可迭代对象内部也可以实现__next__,但是不符合设计模式
新学知识点:对于要处理的数据,我们可以通过实现迭代协议对齐进行优化处理
如下面的MyIterator
from collections.abc import Iterator
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __iter__(self):
return MyIterator(self.employee)
# def __getitem__(self, item): #用来维护索引值(通过下标取值)
# return self.employee[item]
#自定义实现迭代器
class MyIterator(Iterator):
def __init__(self, employee_list):
self.iter_list = employee_list
self.index = 0
def __next__(self):
#真正返回迭代值的逻辑
try:
word = self.iter_list[self.index]
except IndexError:
raise StopIteration
self.index += 1
return word
if __name__ == "__main__":
company = Company(["tom", "bob", "jane"])
my_itor = iter(company)
# while True:
# try:
# print (next(my_itor))
# except StopIteration:
# pass
# next(my_itor)
for item in company:#for内部自动处理了stopIteration
print (item)
三。生成器
#生成器函数,函数里只要有yield关键字
#生成器对象也是实现了迭代器协议的,可以使用for循环
#函数只能返回一个,而生成器也以一直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
四。生成器原理
#1.python中函数的工作原理
"""
"""
import inspect
frame = None
def foo():
bar()
def bar():
global frame
frame = inspect.currentframe()
#python.exe会用一个叫做 PyEval_EvalFramEx(c函数)去执行foo函数, 首先会创建一个栈帧(stack frame)
"""
python一切皆对象,栈帧对象, 字节码对象
当foo调用子函数 bar, 又会创建一个栈帧
所有的栈帧都是分配在堆内存上,这就决定了栈帧可以独立于调用者存在
与静态语言不同,静态语言的函数调用是在栈上,函数执行完毕站就会销毁
而python的函数的执行,是将栈都分配在退内存上,
"""
# import dis
# print(dis.dis(foo))
foo()
print(frame.f_code.co_name)
caller_frame = frame.f_back
print(caller_frame.f_code.co_name)
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)
class company:
def __getitem__(self, item):#通过索引的形式访问
pass
from collections import UserList
对生成器的 进一步封装,f_lasti指向上一次代码执行的位置,f_locals是变量的
生成器对象是分配在退内存中的,可以独立于调用者
list的内部实现的遍历原理