什么是迭代器
在介绍生成器之前,我们必须了解这几个概念的区别。
迭代协议,迭代协议,可迭代对象到底是什么,它们有什么不同。
迭代协议,迭代协议,可迭代对象
什么是迭代协议:
在前一篇提到过,python中魔法函数构成了数据结构自定义的协议。我们可以基于这个协议去定义自己的方法类去达到自己的目的,Python提供了两个魔法方法,分别是__iter__和__next__。又为了支持for...in...行为,牵扯进了__getitem__,这写函数是实现迭代协议的关键。
迭代器是什么?
迭代器是访问集合内元素的一种方式, 一般用来遍历数据,迭代器和以下标的访问方式不一样, 迭代器是不能返回的, 迭代器提供了一种惰性方式数据的方式。
什么是可迭代对象?
Python中可迭代对象(Iterable)并不是指某种具体的数据类型,它是指存储了元素的一个容器对象,且容器中的元素可以通过__iter__( )方法或__getitem__( )方法访问。__iter__方法的作用是让对象可以用for … in循环遍历,getitem( )方法是让对象可以通过“实例名[index]”的方式访问实例中的元素。两个方法的目的是Python实现一个通用的外部可以访问可迭代对象内部数据的接口。
一个可迭代对象是不能独立进行迭代的,而是需要迭代器去迭代。
自定义迭代器
需要两个方法:__iter__, __next__,为了满足设计规范,我们一般将迭代器和迭代对象分开封装。代码如下:
from collections.abc import Iterator
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
def __iter__(self):
return MyIterator(self.employee)
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(["yancy", "yancy1", "yancy2"])
my_itor = iter(company)
for item in company:
print (item)
什么是生成器
生成器函数,函数里只要有yield关键字,生成器对象, python编译字节码的时候就产生了。下面有个用生成器生成斐波那契数的例子。
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):
介绍生成器之前我们得先了解什么是函数,已经python中得函数在内存里是怎么运行的。
python解释器会用一个叫做 PyEval_EvalFramEx(c函数)去执行函数, 首先会创建一个栈帧(stack frame),所有的栈帧都是分配在堆内存上,这就决定了栈帧可以独立于调用者存在。当一个函数又调用子函数,又会创建一个栈帧。
python一切皆对象,函数执行时会生成两个对象栈帧对象, 字节码对象。
函数执行过程如图
注意:和静态的语言函数执行过程不一样,静态语言是会创建一个栈。堆与栈的区别有:1、栈由系统自动分配,而堆是人为申请开辟;2、栈获得的空间较小,而堆获得的空间较大;3、栈由系统自动分配,速度较快,而堆一般速度比较慢;4、栈是连续的空间,而堆是不连续的空间。
生成器原理
生成器的原理是将这些上图中的栈帧又封装了一层
因为有了f_lasti,f_locals,所以生成器可以知道下次从哪里运行。这就是生成器的原理,我将它类比于一个递归函数。
新浪微博|是yancy呀
微信号|ToLiveIsToRest