生成器和迭代器

生成器:

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 对象。

posted @ 2018-09-05 09:55  凌晨四点的洛杉矶  阅读(170)  评论(0编辑  收藏  举报