迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
1. 可迭代对象
以直接作用于 for 循环的数据类型有以下几种:
一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。
2. 判断是否可以迭代
可以使用 isinstance() 判断一个对象是否是 Iterable 对象:
In [50]: from collections import Iterable In [51]: isinstance([], Iterable) Out[51]: True In [52]: isinstance({}, Iterable) Out[52]: True In [53]: isinstance('abc', Iterable) Out[53]: True In [54]: isinstance((x for x in range(10)), Iterable) Out[54]: True In [55]: isinstance(100, Iterable) Out[55]: False
3.迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用 isinstance() 判断一个对象是否是 Iterator 对象:
In [56]: from collections import Iterator In [57]: isinstance((x for x in range(10)), Iterator) Out[57]: True In [58]: isinstance([], Iterator) Out[58]: False In [59]: isinstance({}, Iterator) Out[59]: False In [60]: isinstance('abc', Iterator) Out[60]: False In [61]: isinstance(100, Iterator) Out[61]: False
总结
凡是可作用于 for 循环的对象都是 Iterable 类型;
凡是可作用于 next() 函数的对象都是 Iterator 类型
集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象。
⽣成器
1. 什么是⽣成器
通过列表⽣成式,我们可以直接创建⼀个列表。但是,受到内存限制,列表 容量肯定是有限的。⽽且,创建⼀个包含100万个元素的列表,不仅占⽤很 ⼤的存储空间,如果我们仅仅需要访问前⾯⼏个元素,那后⾯绝⼤多数元素 占⽤的空间都⽩⽩浪费了。所以,如果列表元素可以按照某种算法推算出 来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必 创建完整的list,从⽽节省⼤量的空间。在Python中,这种⼀边循环⼀边计算 的机制,称为⽣成器:generator。
2. 创建⽣成器⽅法1
要创建⼀个⽣成器,有很多种⽅法。第⼀种⽅法很简单,只要把⼀个列表⽣ 成式的 [ ] 改成 ( )
In [15]: L = [ x*2 for x in range(5)] In [16]: L Out[16]: [0, 2, 4, 6, 8] In [17]: G = ( x*2 for x in range(5)) In [18]: G Out[18]: <generator object <genexpr> at 0x7f626c132db0> In [19]:
yield
def createNum(): a = 0 b = 1 for i in range(10): a,b = b,a+b yield b a = createNum() #这里没有执行这个函数 #调用生成器的方法 #方法一 print("----1----") print(next(a)) #从这里开始执行这个函数 print(next(a)) print(next(a)) #方法二 print("----2----") print(a.__next__()) print(a.__next__()) print(a.__next__()) #方法三 print("----3----") for i in a: print(i)
输出
----1---- 1 2 3 ----2---- 5 8 13 ----3---- 21 34 55 89
send
def test(): i = 0 while i < 5: temp =yield i print(temp) i+=1 t = test() print("---1---") print(t.__next__()) print("---2---") print(t.__next__()) print("---3---") print(t.send("haha")) #这里相当于让yield i = "haha",然后temp = "haha" ,接着运行下面的代码
输出
---1--- 0 ---2--- None 1 ---3--- haha 2
多任务(协程)
def test1(): while True: print("---1---") yield None def test2(): while True: print("---2---") yield None t1 = test1() t2 = test2() while True: while True: t1.__next__() t2.__next__()
总结
⽣成器是这样⼀个函数,它记住上⼀次返回时在函数体中的位置。对⽣成器 函数的第⼆次(或第 n 次)调⽤跳转⾄该函数中间,⽽上次调⽤的所有局部 变量都保持不变。
⽣成器不仅“记住”了它数据状态;⽣成器还“记住”了它在流控制构造(在命令 式编程中,这种构造不只是数据值)中的位置。
⽣成器的特点:
1. 节约内存 2. 迭代到下⼀次的调⽤时,所使⽤的参数都是第⼀次所保留下的,即是 说,在整个所有函数调⽤的参数都是第⼀次所调⽤时保留的,⽽不是新 创建的