__iter__
为python中的内建函数,如果想要定义的对象是iterable,你就需要定义__iter__
next(__next__
)常与__iter__
共同使用,构成迭代器(iterator)
带有yield关键字的函数为生成器(generator)
为了理解这几个关键字和迭代器、生成器。我们从一个常用的斐波那契数列(Fibinacci)开始
def fib(max):
n,a,b = 0,0,1
fib_list = []
while n < max :
fib_list.append(b)
a,b = b, a+b
n = n +1
return fib_list
当我们调用fib(max=100000)时,该函数返回长度为100000的list,显然max较大的时候会占用较大的内存,尤其是如果我们每次并不需要使用整个列表,而是取其中的一个item而已,在这个时候,返回list就不是那么明智了(同理,在 for i in xrange(100)
与for i in range(100)
两者中,前者是推荐的循环的方式)
为了解决上述问题,我们引入迭代器的概念。
迭代器(iterator)与可迭代(iterable)并不是一个概念,list,dict
这些都是可迭代的,但只有实现了next方法(python 2.x为next,而Python 3变成了__next__
)的对象才是迭代器。在调用next
方法时,迭代器会返回它的一下个值,如果next方法被调用,但是迭代器没有值可以返回,会引发一个StopIteration
异常,在for循环内无需处理该异常,循环会正常结束。
class Fib_iterator(object):
def __init__(self,max):
self.max = max
self.n,self.a,self.b = 0,0,1
def __iter__(self):
return self
def next(self):
if self.n < self.max:
r = self.b
self.a ,self.b = self.b,self.a + self.b
self.n = self.n + 1
return r
raise StopIteration()
Fib类通过for循环迭代,for n in Fib_iterator(5)
每次for循环迭代,Fib类通过next()方法返回数列的下一个数,所以迭代器实现比常规实现内存消耗小。但是我们注意到,利用迭代器实现的的方法需要实现__iter__
、next
等方法使得代码过于复杂,因此,我们引入生成器。
生成器是Python新引入的概念,可以帮助我们写出更优雅(Pythonic)的代码。生成器是一种用普通的函数语法定义的迭代器,该函数包含yield
关键字。当它被调用时,在函数体内的代码不会被执行,而是返回一个迭代器。当在for
循环中请求一个值时,就会执行生成器中的代码,直到遇到了yield
或return
语句。
def fib_generator(max):
n,a,b = 0,0,1
while n<max:
yield b
a,b = b,a+b
n = n + 1
可以看出来,生成器帮助我们在保持代码简洁的情况下同时保证最低的内存消耗(每次只取一个值)。我们仍然利用for循环迭代,for n in fib_generator(5)
,当函数执行到yield时,函数中断通过yield返回当前的值,当再次请求下一个值时,从yield 的下一个语句继续执行。
评论 (0)