一.可迭代对象
在介绍迭代器与生成器之前,我们首先来介绍一下可迭代对象。可迭代对象,顾名思义,就是可以“迭代”的对象。所谓迭代,就是一个 通过for循环遍历出对象中所有元素 的过程。那么可迭代对象,便是可以实现这个过程的对象了。
在Python中,很多对象都是可迭代的,比如列表(list)、字典(dict)、元组(tuple)、集合(set)、字符串(str)、字节(bytes)等等,并且这些可迭代对象,都实现了__iter__()魔法方法。
二.迭代器(iterator)
1.迭代器的定义
迭代器属于可迭代对象,但又与可迭代对象有一点不同,它的定义是:一种可以作用于next函数的可迭代对象。迭代器不仅实现了__iter__()方法,而且实现了__next__()方法,这是区别迭代器与可迭代对象的一个重要特征!
2.迭代器的创建
(1)我们可以通过 iter(iterable) 函数将可迭代对象转换成迭代器,得到一个迭代器对象。
3.迭代器的特点
(1)我们可以通过 iter(iterable) 函数将可迭代对象转换成迭代器,得到一个迭代器对象。
(1)迭代器只可往后遍历,不可回溯。
(2)我们可以使用next()函数一次取出迭代器中的元素,直至取完其中的所有元素。如果取完后继续使用next方法,程序会抛出 StopIteration 异常:
it = iter([0,1,2]) #通过iter()函数的到一个迭代器对象
print(it) #查看迭代器对象
#调用next()函数一次获取迭代器中元素
print(next(it))
print(next(it))
print(next(it))
print(next(it))
打印结果:
我们同样可以通过for循环遍历获得迭代器中的元素。
三.生成器(generator)
1.生成器的定义
我们经常使用列表,字典等可迭代对象来存放数据,但由于内存优先,如果我们要存放的数据非常多,全部放在这些容器中,那么存储空间肯定是不够的,很容易导致内存溢出。为了解决这个问题,就有了生成器这样一个概念:通过存储某种特定的算法,在需要时,一边计算一边调用的机制,成为生成器。
2.生成器的创建
(1)将列表推导式的方括号[]改为()即可的到一个生成器
g = (i for i in range(5))
print(type(g)) #<class 'generator'>
(2)一个函数中若包含了yield关键字,则这个函数就变成了一个生成器
#利用生成器实现的斐波那契数列
def fibonacci(n):
a, b, num = 0, 1, 0
while n > num:
yield a #将a的值返回出去再继续执行后续代码
a, b = b, a+b
num += 1
f = fibonacci(5)
print(type(f)) #<class 'generator'>
3.生成器的特点
(1)生成器同样可以通过next()函数进行调用
g = (i for i in range(5))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
打印结果:
生成器也可以通过for循环进行遍历
(2)yield关键字
yield关键字和函数中的return很像,都是将函数执行的结果返回出去,但yield关键字在执行后不会像return一样立即退出函数体,而是暂停,等待下一次启用生成器继续在该函数体内作用。return 与 yield 的关系可以类比循环中的break 和 continue 的关系。
(3)生成器的send()方法
send()方法和next()方法一样,可以启动生成器,不同的时send可以向生成器中传入值,如图:
我们第一次next(f)后,程序执行到yield i 返回i的值给f,并且暂停。
第二次next(f)程序从上一次暂停的位置继续向后执行,由于yield i 将i的值返回给了f,即此时的 等号右边的值为空值None 因此None被赋值给了a,接下来执行print(a)打印出来的值就变成了None;接着程序继续执行,进入第二次循环,此时i值为1,再次碰到yield i ,又一次将i返回给f,因此此时输出了1,程序暂停。
第三次,我们使用send()方法,向生成器中传入数据‘666’。send方法和next一样,再次启动生成器,程序从第二次暂停的地方 yield i 后开始执行,由于我们使用了send方法,该方法会在此时将由于返回出去i而变为空值None的等号右边重新赋值为传入的数据’666’,即此时 a = ‘666’,接下来执行print(a)将打印出666;接下来程序继续执行,再一次进入循环,此时i的值变为2,再次执行到yield i 将i返回给f ,输出2。
通过这个例子,我们就可以对生成器的 yield 关键字和send()方法有了基本的一些了解。