python 迭代器&生成器

人工智能炼丹师
2019-03-24 / 0 评论 / 147 阅读 / 正在检测是否收录...

__iter__为python中的内建函数,如果想要定义的对象是iterable,你就需要定义__iter__
next(__next__)常与__iter__共同使用,构成迭代器(iterator)
带有yield关键字的函数为生成器(generator)

为了理解这几个关键字和迭代器、生成器。我们从一个常用的斐波那契数列(Fibinacci)开始

常规实现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循环内无需处理该异常,循环会正常结束。

用迭代器实现Fibinacci序列

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循环中请求一个值时,就会执行生成器中的代码,直到遇到了yieldreturn语句。

用生成器实现Fibinacci序列

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

评论 (0)

取消
粤ICP备2021042327号