迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
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. 迭代到下⼀次的调⽤时,所使⽤的参数都是第⼀次所保留下的,即是 说,在整个所有函数调⽤的参数都是第⼀次所调⽤时保留的,⽽不是新 创建的