zoukankan      html  css  js  c++  java
  • python 生成器与迭代器(yield 用法)

    背景

    首先,我不会解释这两个名词,我看过很多遍解释,可还是看不懂,还是直接看使用情景吧。
    我们以佩波拉契数列为例,当我们不知道迭代器的情况下,我们写出来的代码可能是这样子的:

    '''这种方式计算fib(100)都很吃力'''
    fib = lambda n:fib(n-2) + fib(n-1) if n>1 else 1
    

    或者优化一下,变成这样子:

    '''
    将迭代结果存入temp中,避免重复的计算, 
    这样可以提高计算速度,但是当计算fib(4000)时,会报:
    “maximum recursion depth exceeded in comparison”
    也就是说会超过最大迭代次数
    '''
    temp = {}
    def fib(n):
        if n in temp:
            return temp[n]
        
        if n>1:
            _t = fib(n-1) +  fib(n-2)
            temp[n] = t
            return _t
        else:
            return 1
    

    考虑到进一步的优化,我们就需要引进python的yield 语法

    使用yield

    yield的用法简单来说就 返回yield运行结果,当调用__next__时,再次运行至yield处,并返回 。所以我们可以利用这一特点,让fib函数每次只返回当前和前一个的值,再次运行时更新这两值, 并返回就好了。于是有了下面的代码:

    '''
    这次我们可以最大程度发挥计算机性能,
    比上个版本能计算的更多也更快(我电脑能计算6位数的fib值)
    '''
    def fib_gen():
        '''
        这时一个佩波拉契数列的生成器,每次迭代返回当前值和前一个的值
        '''
        c , p = 1,1
        while True:
            yield p # 每次next运行到此,并返回p的值。当再次调用时,继续执行下面代码,
            p, c = c, c+p # 计算下次p的值
            
    def fib(n):
        '''根据情况不断运行next(f),直到适合的条件'''
        f = fib_gen()
        for i in range(n+1):
            cur = next(f)
        return n
    

    我们在看一个简单的生成器的例子

    In [1]: array = [1,2,3,4]
    
    In [2]: f = (i for i in array) # 是不是看起来很像“元组推倒式”,其实这是一个生成器。python并没有元组的推倒式
    
    In [3]: f # 不信,我们来实际看看
    Out[3]: <generator object <genexpr> at 0x10882df10>
    
    In [4]: [i for i in f] # 生成器是可以迭代的,所以列表推到能取出值
    Out[4]: [1, 2, 3, 4]
    
    In [5]: [i for i in f]
    Out[5]: [] # 此时,f中的数据全部取出,调用next(f) 取不出来值了
    

    总结

    • 从这个例子中我们可以发现,当使用yield后,函数并不是立刻执行,而是调用next的时候,我们才取出值,没调用的时候,它只是一个生成器。相当于保存了上次运行的现场。
    • 当调用next时,没有找到yield返回时,便会终止,并报StopIteration错误, 本例子中是死循环,不会发生这种情况。感兴趣的可以把while True 改成while p < 100之类的试试
  • 相关阅读:
    微信小程序退款【证书的使用】
    生成随机位数的UUID
    弹出层-layui
    load加载层-layui
    form-layui
    table-layui
    下拉列表模仿placeholder效果
    .net core 2.0 Unable to convert MySQL date/time to System.DateTime
    .net core Include问题
    .net core 2.0 配置Session
  • 原文地址:https://www.cnblogs.com/yuzhenjie/p/9404438.html
Copyright © 2011-2022 走看看