• 从零开始的Python学习Episode 12——迭代器&生成器


    生成器

    列表生成式

    用于快速地生成一个列表

    a = [x*x for x in range(1,9)]
    print(a)
    
    #输出[1, 4, 9, 16, 25, 36, 49, 64]
    

    也可以用于生成函数结果的列表

    def f(n):
        return n**3
    
    a = [f(x) for x in range(1,9)]
    print(a)
    
    #输出[1, 8, 27, 64, 125, 216, 343, 512]
    

      

    迭代器

    迭代器是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__()方法的对象都是迭代器。

    拿斐波拉契数列作例子

    def fib(max): 
        L = []
        n, a, b = 0, 0, 1 
        while n < max: 
            L.append(b) 
            a, b = b, a + b 
            n = n + 1
        return L
    

      这种用法会如果max的很大的话会占用特别多的内存,导致程序卡顿。

    使用迭代器可以解决复用可占空间的问题

    迭代器可以通过 next() 不断返回数列的下一个数,内存占用始终为常数。

    class Fib(object): 
        def __init__(self, max): 
            self.max = max 
            self.n, self.a, self.b = 0, 0, 1 
    
        def __iter__(self): 
            return self 
    
        def next(self): 
            if self.n < self.max: 
                r = self.b 
                self.a, self.b = self.b, self.a + self.b 
                self.n = self.n + 1 
                return r 
            raise StopIteration()
    

      

    生成器

    生成器其实是一种特殊的迭代器。生成器(yield)既可以保持代码的简洁性,又可以减少占用内存的效果。它不需要再像上面的类一样写 __iter__() 和 __next__() 方法了,只需要一个 yiled 关键字。

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a + b
            n = n + 1
    
    for n in fib(5):
        print(n)
    
    #输出
    1
    1
    2
    3
    5
    

      yield 的作用就是把一个函数变成一个生成器,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个生成器,在 for 循环执行时,每次循环都会执行 fib 函数内部的代码,执行到 yield b 时,fib 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

    (1)send()方法

    send方法可以往生成器里传值

    def f():
        print("ok")
        n = yield
        print(n)
        print("ok2")
        yield 2
    f = f()
    f.send(None)
    f.send(1)
    next(f)
    #输出
    ok
    Traceback (most recent call last):
    1
    ok2
      File "D:/PyCharm Project/test/Starter/test2.py", line 10, in <module>
        next(f)
    StopIteration
    

      send方法会把值传到yield前的对象,并往下执行到下一个yield。但当使用send之前要先用next或者用send(None)来获取yield的位置,否则无法把值传给yield。

    还有一点:

    在一个生成器中,如果没有return,则默认执行到函数完毕;如果遇到return,如果在执行过程中 return,则直接抛出 StopIteration 终止迭代。而for不报错的原因是内部处理了迭代结束的这种情况。

    是一个带状态的对象,他能在你调用 next() 方法的时候返回容器中的下一个值,任何实现了 __next__() (python2中实现 next() )方法的对象都是迭代器

  • 相关阅读:
    uni-appios端app白屏问题
    vue中倒计时假清除
    vue路由守卫
    JS函数命名规范
    VUE生成二维码
    移动端H5之css配置rem
    关于在vue中使用ui库样式无法修改的问题
    v28 error: resource android:attr/dialogCornerRadius not found.
    cocos2d: fullPathForFilename: No file found at script/jsb_prepare.js. Possible missing file
    android studio clean show: CreateProcess error=2, 系统找不到指定的文件。
  • 原文地址:https://www.cnblogs.com/smilepup-hhr/p/9788894.html
Copyright © 2020-2023  润新知