zoukankan      html  css  js  c++  java
  • 迭代器,生成器,yield,yield from理解

    迭代器

    说到迭代器就得想说可迭代对象Iterable,实现了__iter__()方法的对象都是可迭代对象,例如很多容器,list ,set, tuples。使用iter方法可以把一个可迭代对象变成迭代器

    迭代器是实现了__next__()方法的可迭代对象,也就是说迭代器必须实现__iter__()和__next__()方法,迭代器可以调用next()放不断的迭代,在给定的范围中返回数据,超出范围抛出异常。

    几个有趣的例子:

    from itertools import count
    counter = count(start=13)
    next(counter)
    13
    next(counter)
    14   无限序列只要你愿意可以一直迭代下去,然而你无法创建一个这么大的list是不是可以说的迭代器的优点呢
    from itertools import cycle
    colors = cycle(['red', 'white', 'blue'])
    print next(colors)
    # 'red'
    print next(colors)
    # 'white'
    print next(colors)
    # 'blue'
    print next(colors)
    # 'red'   无限循环序列
    from itertools import islice,cycle
    colors = cycle(['red', 'white', 'blue'])
    limited = islice(colors, 0, 6)            
    for x in limited:
        print(x)
    #有限序列
    from itertools import islice
    class Fib:
        def __init__(self):
            self.prev = 0
            self.curr = 1
        def __iter__(self):
            return self
    
        def __next__(self): #注意在python2中需要写成next() python3中写成__next__()
            value = self.curr
            self.curr += self.prev
            self.prev = value
            return value
    f = Fib()
    print(list(islice(f, 0, 10)))

    生成器

    简单的生成器(x for x in range(5)) 和列表生成式很像,如果生成的逻辑比较复杂,用类似列表生成式的方式难以表达,我们可以用函数加关键字yield的方式。

    在我的理解中,生成器generator是一种特殊的迭代器,他用yield来自动实现了__iter__()和__next__()方法

    那我们用yield来实现一下斐波拉契:

    def fib():
        prev = 0
        curr = 1
        while True:
            value = curr
            yield value
            curr += prev
            prev = value
    a = fib()
    for x in range(10):
        print(next(a))

    yield 

    这个yield这么神奇吗?到底该怎么理解它呢?首先你可以把它当成一个return,之后就不再继续往下执行了,调用next()方法后继续执行,举个例子。

    def foo():
        print("starting...")
        while True:
            res = yield 4
            print("res:",res)
    g = foo()
    print(next(g))
    print("*"*20)
    print(next(g))

    starting...
    4    # 走到yield 4的时候马上return 4(马上返回并没有赋值操作),
    ********************
    res: None  #接着 yield 继续往下走,进行赋值操作,4已经被return 出去了,所以res=None
    4  # 进入下一个循环,又走到yield 4

    我们稍微修改一下函数

    def foo():
        print("starting...")
        while True:
            res = yield 4
            print("res:",res)
    g = foo()
    print(next(g))
    print("*"*20)
    print(g.send(7))

    starting...   
    4
    ********************
    res: 7   #挺神奇的怎么变成7了,注意我们此时用的是send()方法,它是传递了一个值给yield表达式,相当于res=7
    4

    yield from 

    yield 是从生成器里返回一个元素,那么yield from 从名字上理解就应该是返回一个生成器咯

    def foo():
        yield from [1,2,3]
    
    a = foo()  
    print(next(a))
    print(next(a))
    print(next(a))
    结果:

    1
    2
    3

    是不是就可以理解为yield from 返回的是 iter([1,2,3])呢

    下面看两个例子

    def foo():
        for i in range(5):
            if i == 2:
                return 'gg'
            else:
                yield i
    a = foo()
    for i in a:
        print(i)

    0
    1

    def foo():
        for i in range(5):
            if i == 2:
                return 'gg'
            else:
                yield i
    a = foo()
    for i in range(5):
        print(next(a))
    0
    1
    StopIteration: gg

    这是yield的特性,在使用for循环取遍历生成器的时候是不会触发StopIteration异常,使用next()可以触发,如果我们又想用for循环遍历又想触发异常怎么弄,再封装一下

    def foo():
        for i in range(5):
            if i == 2:
                return 'gg'
            else:
                yield i
    
    def fun(generator):
        res = yield from generator
        print(res)
    
    a = foo()
    b = fun(a)
    for x in b:
        print(x)

    0
    1
    gg   # 捕捉到了异常并且把return 的值给了yield from 表达式

  • 相关阅读:
    python开发必备:virtualenv虚拟环境(自用)
    JavaScript经典实例
    javascript事件驱动及事件处理
    在HTML网页中嵌入脚本的方式
    JavaScript数据结构
    JavaScript语言调试技巧
    CSS+DIV布局
    在HTML文档中应用CSS
    CSS常用属性
    定义CSS
  • 原文地址:https://www.cnblogs.com/tigerzhouv587/p/11321356.html
Copyright © 2011-2022 走看看