生成器和迭代器
生成器:
Python中,一边循环一边计算的机制,称为生成器:generator
创建生成器方法1
把一个列表生成式的 [ ] 改成 ( )
L = [ x*2 for x in range(5)]
L
Out: [0, 2, 4, 6, 8]
G = ( x*2 for x in range(5))
G
Out: <generator object <genexpr> at 0x7f626c132db0>
访问生成器的元素:
-调用next(G)
-使用 for 循环,因为生成器也是可迭代对象
创建生成器方法2
通过函数实现
def fib(nums):
n = 0
a,b = 0,1
while n<nums:
print(b)
a,b = b,a+b
n+=1
return result
#此函数可以打印出斐波拉契数列,把 print(b) 改为 yield b,就构建了一个生成器
def fib(nums):
n = 0
a,b = 0,1
while n<nums:
yield
a,b = b,a+b
n+=1
return result
用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中
#用异常来捕获返回值
f = fib(5)
while True:
try:
x = next(f)
print("value:%d"%x)
except StopIteration as e:
print("生成器返回值:%s"%e.value)
break
value:1
value:1
value:2
value:3
value:5
生成器返回值:result
send和next
def fun():
i = 0
while i<5:
temp = yield i //返回i的值,并接受一个send()函数的输入,没有的话就是None
print(temp)
i+=1
f = fun()
调用 f.__next__() #f.__next__() 或者 next(f)
f.__next__()
Out: 0
f.__next__()
None
Out: 1
f.__next__()
None
Out: 2
f.__next__()
None
Out: 3
f.__next__()
None
Out: 4
f.__next__()
None
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-17-468f0afdf1b9> in <module>()
----> f.__next__()
执行到yield时,fun函数作用暂时保存,返回i的值;
temp接收下次f.send("xxx") 发送过来的值,f.next()等价f.send(None)
生成器的特点:
节约内存
迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
迭代器
迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
1. 可迭代对象
以直接作用于 for 循环的数据类型有以下几种:
- 集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
- generator ,包括生成器和带 yield 的generator function
这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable 。
2. 判断是否可以迭代
可以使用 isinstance() 判断一个对象是否是可迭代对象:
from collections import Iterable
isinstance([], Iterable)
Out: True
isinstance({}, Iterable)
Out: True
isinstance('abc', Iterable)
Out: True
isinstance((x for x in range(10)), Iterable)
Out: True
isinstance(100, Iterable)
Out: False
3. 判断是否是迭代器
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用 isinstance() 判断一个对象是否是 Iterator 对象
from collections import Iterator
isinstance((x for x in range(10)), Iterator)
Out: True
isinstance([], Iterator)
Out: False
isinstance({}, Iterator)
Out: False
isinstance('abc', Iterator)
Out: False
isinstance(100, Iterator)
Out: False
4. iter()函数
生成器都是 Iterator 对象,但 list 、 dict 、 str 虽然是 Iterable ,却不是 Iterator 。
把 list 、 dict 、 str 等 Iterable 变成 Iterator 可以使用 iter() 函数:
isinstance(iter([]), Iterator)
Out: True
isinstance(iter('abc'), Iterator)
Out: True
总结
-凡是可作用于 for 循环的对象都是 Iterable 类型;
-凡是可作用于 next() 函数的对象都是 Iterator 类型
-集合数据类型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象。