递归和生成器函数

递归

如果函数包含了对其自身的调用,该函数就是递归。递归广泛应用于语言识别和使用递归函数的数学应用中。例如:斐波那契数列和求阶乘等。下面就上面两种使用举例:
斐波那契数列:

In [12]: def fib(n):
                if n==0:
                    return 1
                if n==1:
                    return 1
                return fib(n-2)+fib(n-1)

In [18]: fib(10)
Out[18]: 89

阶乘:

In [19]: def fn(n):
   ....:     if n==0:
   ....:         return 1
   ....:     if n==1:
   ....:         return 1
   ....:     return n*fn(n-1)

In [20]: fn(10)
Out[20]: 3628800

由于递归总是涉及到压栈和出栈,所以递归函数在Python中非常慢,并且有深度限制,所以尽量避免使用递归。在Python中递归的限制可以通过 sys.getrecursionlimit() 得到深度限制,通过sys.setrecursionlimit调整递归深度限制。
注意:循环都可以转化为递归,但不是所有递归都可以转化为循环。

生成器函数

生成器函数是一个带yield语句的函数。一个函数或者子程序只能返回一次,但一个生成器能暂停执行并返回一个中间的结果,这就是yield的功能,返回一个值给调用者并暂停执行。当生成器被next()方法调用的时候,它会准确的从离开地方继续。
请注意yield和return的区别:

  • yield 弹出值,暂停函数

  • return返回值, 并且结束函数

  • 当yield和return同时存在时, return的返回值会被忽略,但是return依然可以中断生成器

In [50]: def gen(x):
   ....:     for i in range(10):
   ....:         if i ==3:
   ....:             return i
   ....:         yield i
   
In [51]: g = gen(10)

In [52]: for i in g:
   ....:     print(i) 
0
1
2

注意:可以使用生成器来替换递归,同时所有的递归,都可以用生成器替换。

In [54]: def fn1():
                ret =1
                index=1
                while True:
                    yield ret
                    index += 1
                    ret *= index

In [55]: g1=fn1()

In [56]: next(g1)
Out[56]: 1

In [57]: next(g1)
Out[57]: 2

In [58]: next(g1)
Out[58]: 6

In [59]: next(g1)
Out[59]: 24

In [60]: next(g1)
Out[60]: 120
def g(n):
    def factorial():
        ret = 1
        idx = 1
        while True:
            yield ret
            idx += 1
            ret *= idx
    gen = factorial()
    for _ in range(n-1):
        next(gen)
    return next(gen)

In [63]: fn2(5)
Out[63]: 120

In [64]: fn2(6)
Out[64]: 720

生成器函数的列表传参
在Python2 中使用:

In [1]: lst = [1,2,3,4,5,7,9]

In [2]: def gen(lst):
   ...:     for x in lst:
   ...:         yield x        

In [3]: g=gen(lst)

In [4]: for i in g:
   ...:     print(i) 
1
2
3
4
5
7
9

在Python3 中使用:

In [5]: def gen1(lst):
   ...:     yield from lst

In [6]: g1=gen1(lst)

In [7]: for j in g1:
   ...:     print(j)
1
2
3
4
5
7
9
原文地址:https://www.cnblogs.com/cuchadanfan/p/5926080.html