原标题:Python生成器之懒人版本的迭代器
从容器、可迭代对象谈起
所有的容器都是可迭代的(iterable),迭代器提供了一个next方法。iter()返回一个迭代器,通过next()函数可以实现遍历。
除了数字外,其他数据结构都是可迭代的。
生成器是什么
生成器是懒人版本的迭代器。例:
[i for i in range(100000000)] 声明了一个迭代器,每个元素在生成后都会保存到内存中,占用了巨量的内存。(i for i in range(100000000)) 初始化了一个生成器,可以看到,生成器并不会像迭代器一样占用大量的内存,相比于 test_iterator(),test_generator()函数节省了一次生成一亿个元素的过程。在调用next()的时候,才会生成下一个变量.
生成器能玩啥花样
数学中有一个恒等式,(1 + 2 + 3 + … + n)^2 = 1^3 + 2^3 + 3^3 + … + n^3,用以下代码表达
generator()这个函数,它返回了一个生成器,当运行到yield i ** k时,暂停并把i ** k作为next()的返回值。每次调用next(gen)时,暂停的程序会启动并往下执行,而且i的值也会被记住,继续累加,最后next_1为8,next_3为512.
仔细查看这个示例,发现迭代器是一个有限集合,生成器则可以成为一个无限集。调用next(),生成器根据运算会自动生成新的元素,然后返回给你,非常便捷。
再来看一个问题:给定一个list和一个指定数字,求这个数字在list中的位置:
再看一例子:
查找子序列:给定两个字符串a,b,查找字符串a是否字符串b的子序列,所谓子序列,即一个序列包含在另一个序列中并且顺序一致。[1,3,5]是[1,2,3,4,5]子序列,而[1,4,3]不是 [1,2,3,4,5] 的子序列.
算法:分别用两个指针指向两个字符串的头,然后往后移动找出相同的值,如果其中一个指针走完了整个字符串也没有相同的值,则不是子序列
下面代码为上面代码的演化版本
首先iter(b)把b转为迭代器。目的是内部实现next函数,(i for i in a) 会产生一个生成器 ,同样((i in b) for i in a)也是。然后(i in b)等阶于:
这里非常巧妙地利用生成器的特性,next()函数运行的时候,保存了当前的指针。比如下面这个示例
责任编辑: