python中的迭代器与生成器

1.什么是迭代器?

在说迭代器前,先说可迭代(Interable)。比如,列表、元组、字典已经字符串都是可以迭代的,我们可以用collections中引入Iterable来判断。

from collections import Iterable
print(isinstance([1,2,3],Iterable))  #True

如何判断是不是迭代器呢?可以用Iterator来判断,输出结果是False,列表可迭代,但不是迭代器。

from collections import Iterator
print(isinstance([1,2,3],Iterator))  #False

那怎么把可迭代序列变成迭代器呢?又怎么访问迭代器中的元素呢?

#使用iter()把列表转换成迭代器
lst = [1, 2, 3]
lst_iter = iter(lst)
print(isinstance(lst_iter, Iterator))  #True

#访问迭代器中的元素
#尝试用列表下表的方式访问迭代器中的值,可以看到报错
print(lst_iter[0])  #TypeError: 'list_iterator' object is not subscriptable

#用next()和for语句
print(next(lst_iter))  #1

最后,来总结一下,什么是迭代器?以及它的两个基本方法。
迭代器是访问集合元素的一种方式,是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()

2.什么是生成器?

在此之前先回顾一下推导式,其中最常见的是列表列表推导式,列表推导式代码如下,可以看到lst是列表类型。

lst = [i for i in range(5)]
print(lst,type(lst)) #打印结果: [0, 1, 2, 3, 4] 

如果我们把上面的[ ]换成( ),输出结果是应该是什么呢?是元组推导式?

lst = (i for i in range(5))
print(lst,type(lst)) #打印结果:  at 0x000001CC28F48150> 

从运行的结果看,有两点不同。第一,没有向上面列表推导式一样直接打印出数字序列;第二,类型也从list变成了generator,generator也就是生成器。

yield关键字

此外,在使用了yield关键字的函数也称为生成器。与普通函数相比,生成器是返回迭代器的函数。同时,生成器也是一种特殊的迭代器。所以,我们也可以像迭代器一样使用next()和for来获取生成器中的元素。

def myG():
    for i in range(3):
        print('before yield')
        yield i
        print('after yield')
g = myG()
print(next(g))
#运行结果分别是:
#before yield
#0

从执行结果可以看出两点:第一,执行一次next(g),打印了before yield和0,可以知道函数运行到了yield i 这一行。第二,yield i 这一行返回了i的值,yield i作用类似于return i。与return不同的是,return后面的代码不再执行,yield后面的代码在一下次访问的时候接着执行。

def myG():
    for i in range(3):
        print('before yield')
        yield i
        print('after yield')
g = myG()
print(next(g))
print(next(g))

#运行结果分别是:
#before yield
#0
#after yield
#before yield
#1

#打印生成器
print(g)  #

执行两次next(),运行结果与第一次对比,多了3行输出。可以看到,第二次执行next()时,函数从yield i后面继续执行,并在下一次循环后又停留在了yield i处。
可以发现,生成器并不能直接用print()输出其中的元素,需要用next()或者for来访问时才输出。所以,生成器可以用于节省内存空间,因为它是在访问时才使用,可以在交互式环境下比较两者的区别(运行前注意保存文件)。

a = [i for i in range(10**20)]
b = (i for i in range(10**20))

你可能感兴趣的:(python中的迭代器与生成器)