跳转至

迭代器与生成器

迭代 在编程中是一个非常重要的术语 百科讲解 - 迭代。 计算机特定程序中需要反复执行的子程序(一组指令),进行一次重复,即重复执行程序中的循环,直到满足某条件为止,称为迭代。 白话的说,给定一个List或者Tuple,通过 for 循环来遍历它们,这种遍历就可称为迭代。

例如:

for c in 'python':
    print(c)

列表生成式

列表生成式(List Comprehensions)是用来创建list的生成式。

语法为:

[expr for iter_var in iterable] 
[expr for iter_var in iterable if cond_expr]

例如,生成 100 以内的所有偶数列表:

list = [x for x in range(1, 100) if x % 2 == 0]

iterator 迭代器

迭代器是一个可以记住遍历的位置的对象 , 迭代器有两个基本的方法:iter() 和 next(),迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。

集合数据类型,如 listtupledictsetstr 等都可以使用 迭代器 来进行遍历。

# list对象创建迭代器
list = [x for x in range(1, 100) if x % 2 == 0]
iter = iter(list)

# for 循环遍历迭代器对象
for x in iter:
    print(x, end=',')

generator 生成器

在上面我们介绍了列表生成式,而生成器与生成式的语法非常类似,例如,新建一个 生成 100 以内的所有偶数 的生成器:

g = (x for x in range(1, 100) if x % 2 == 0)
print(next(g))
print(next(g))
print(next(g))

输出:

2
4
6

有没有发现,只是把 []替换成了 () 就变成了生成器。

我对生成器的理解是,它是一个保存算法的容器,如上例,你只需要知道如何计算出100以内的算法,你把这段算法使用()包裹起来,那么它就是一个生成器。而假如你使用[]包裹起来,那它就是一个列表生成列。

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

遍历生成器的元素

generator是可迭代的:

g = (x for x in range(1, 100) if x % 2 == 0)
for x in g:
    print(x)

以函数的形式实现生成器

一般写法:

# -*- coding: UTF-8 -*-
def even_number():
    for x in range(1, 100):
        if x % 2 == 0:
            print(x)

even_number()

生成器写法:

# -*- coding: UTF-8 -*-
def even_number():
    for x in range(1, 100):
        if x % 2 == 0:
            yield x

g = even_number()

此时even_number返回就是一个生成器

斐波那契数列

生成器的最好的应用应该是:你不想同一时间将所有计算出来的大量结果集分配到内存当中,特别是结果集里还包含循环。因为这样会耗很大的资源。

而斐波那契数列就是一个非常好的应用实例,请先到百科中查阅 斐波那契数列 的定义。

# -*- coding: UTF-8 -*-
def fib(n):
    a = b = 1
    for i in range(n):
        yield a
        a, b = b, a + b


# 引用函数
for x in fib(10000):
    print(x, end=',')

generator 和函数的执行流程不一样。函数是顺序执行,遇到 return 语句或者最后一行函数语句就返回。而变成 generator 的函数,在每次调用 next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。


参考链接: