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