迭代器和生成器总结

迭代器:python


是一个抽象的概念,任何对象,若是它的类有 next 方法和 iter 方法返回本身自己,对于 string、list、dict、tuple 等这类容器对象,使用 for 循环遍历是很方便的。在后台 for 语句对容器对象调用 iter()函数,iter()是 python 的内置函数。iter()会返回一个定义了 next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是 python 的内置函数。在没有后续元素时,next()会抛出一个 StopIteration 异常。函数


关于iter()和next():工具


一、iter(iterable)函数是把可迭代对象的迭代器取出来,内部是调用可迭代对象的__iter__方法,来取得迭代器的
二、next(iterator)函数是经过迭代器取得下一个位置的值,内部是调用迭代器对象的__next__方法,来取得下一个位置的值
注意: 
当咱们已经迭代完最后一个数据以后,再次调用next()函数会抛出StopIteration的异常,来告诉咱们全部数据都已迭代完成,不用再执行next()函数了。
因此:
咱们要想构造一个迭代器,就要实现它的__next__方法。但这还不够,python要求迭代器自己也是可迭代的,因此咱们还要为迭代器实现__iter__方法,而__iter__方法要返回一个迭代器,迭代器自身正是一个迭代器,因此迭代器的__iter__方法返回自身便可。
结论: 
一个实现了__iter__方法和__next__方法的对象,就是迭代器,迭代器同时也是一个可迭代对象spa


示例代码:code

class FibIterator(object):
    """斐波那契数列迭代器"""

    def __init__(self, n):
        # 记录生成fibonacci的数列的个数
        self.n = n
        # 记录当前遍历的下标
        self.current_index = 0
        # 记录fibonacci数列前面的两个值
        self.num1 = 0
        self.num2 = 1

    def __next__(self):
        """被next()函数调用来获取下一个数"""
        if self.current_index < self.n:
            num = self.num1
            self.num1, self.num2 = self.num2, self.num1 + self.num2
            self.current_index += 1
            return num
        else:
            raise StopIteration

    def __iter__(self):
        """迭代器的__iter__返回自身便可"""
        return self


if __name__ == '__main__':
    fib = FibIterator(10)
    for num in fib:
        print("  ", num, end="")

# 运行结果: 0 1 1 2 3 5 8 13 21 34

 

生成器(Generator):对象


是建立迭代器的简单而强大的工具。生成器是一种特殊的迭代器,它比迭代器写起来更加优雅,它们写起来就像是正规的函数,只是在须要返回数据的时候使用 yield 语句。每次 next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和全部的数据值)blog

 

最简单的生成器就是把一个列表生成式的[ ]改为( )
例如:g = (x*2 for x in rang(5)),就是一个生成器
另一种生成器的建立方法就是这一个函数里面加yield:
例如把上面的斐波那契函数改写成生成式以下:内存

def fib(n):
    current_index = 0
    num1, num2 = 0, 1
    while current_index < n:
        # print(num1) # 打印斐波那契数列
        """
         1. 假如函数中有yield,则再也不是函数,而是生成器
         2. yield 会产生一个断点
         3. 假如yield后面紧接着一个数据,就会把数据返回,
            做为next()函数或者for ...in...迭代出的下一个值
        """
        yield num1
        num1, num2 = num2, num1 + num2
        current_index += 1

if __name__ == '__main__':
    # 假如函数中有yield,则再也不是函数,而是一个生成器
    gen = fib(10)

    #  生成器是一种特殊的迭代器
    for num in gen:
        print(num)

# 运行结果: 0 1 1 2 3 5 8 13 21 34

经过代码能够很直观看出生成器更优雅更省代码ci

yield其实就是保存当前程序执行状态。你用 for 循环的时候,每次取一个元素的时候就会计算一次。用 yield 的函数叫 generator,和 iterator 同样,它的好处是不用一次计算全部元素,而是用一次算一次,能够节省不少空间。generator每次计算须要上一次计算结果,因此用 yield,不然一 return,上次计算结果就没了,简单来讲一个函数里面加了yield就是生成器。
还有咱们除了可使用next()函数来唤醒生成器继续执行外,还可使用send()函数来唤醒执行。使用send()函数的一个好处是能够在唤醒的同时向断点处传入一个附加数据。generator

总结:


一、使用了yield关键字的函数再也不是函数,而是生成器。(使用了yield的函数就是生成器)
二、yield关键字有两点做用:
 保存当前运行状态(断点),而后暂停执行,即将生成器(函数)挂起
 将yield关键字后面表达式的值做为返回值返回,此时能够理解为起到了return的做用
三、可使用next()函数让生成器从断点处继续执行,即唤醒生成器(函数)

 

区别:


生成器能作到迭代器能作的全部事,并且由于自动建立了 iter()和 next()方法,生成器显得特别简洁,并且生成器也是高效的,使用生成器表达式取代列表解析能够同时节省内存。除了建立和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。

相关文章
相关标签/搜索