Python 递归函数和匿名函数

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

1
2
3
4
5
6
7
8
   def fact(x):

if x ==1:
return 1
return x * fact(x-1)


print(fact(3)) //输出6 = 2*2*2

使用递归函数需要防范栈溢出,在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    def fact(x):

if x ==1:
return 1
return x * fact(x-1)


print(fact(1000))

```
报错

```python

/Users/wenjun/PycharmProjects/python2018/venv/bin/python /Users/wenjun/PycharmProjects/python2018/day01/defdemo.py
Traceback (most recent call last):
File "/Users/wenjun/PycharmProjects/python2018/day01/defdemo.py", line 80, in <module>
print(fact(1000))
File "/Users/wenjun/PycharmProjects/python2018/day01/defdemo.py", line 77, in fact
return x * fact(x-1)
File "/Users/wenjun/PycharmProjects/python2018/day01/defdemo.py", line 77, in fact
return x * fact(x-1)
File "/Users/wenjun/PycharmProjects/python2018/day01/defdemo.py", line 77, in fact
return x * fact(x-1)
[Previous line repeated 994 more times]
File "/Users/wenjun/PycharmProjects/python2018/day01/defdemo.py", line 75, in fact
if x ==1:
RecursionError: maximum recursion depth exceeded in comparison

解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。

尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况。

1
2
3
4
5
6
7
8
9
10
11
12
def fact(n):

return fact_iter(n,1)

def fact_iter(num,product):

if num == 1:
return product
return fact_iter(num-1,num*product)


print(fact_iter(2,120))

匿名函数

当我们在传入函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

1
2

print(list(map(lambda x:x*x,[1,2,3,4,5,6,7,8,9])))

输出

1
2

[1, 4, 9, 16, 25, 36, 49, 64, 81]

通过对比可以看出,匿名函数lambda x: x * x实际上就是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    def f(x):
return x * x
```

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

```python
>>> f = lambda x: x*x
>>> f
<function <lambda> at 0x101bcbe18>
>>> f(5)
25