Python的匿名函数和递归函数

匿名函数 lambda

匿名函数的命名规则,用 lamdba 关键字标识,冒号 : 左侧表示函数接收的参数(a,b) , 冒号 : 右侧表示函数的返回值(a+b)。

因为 lamdba 在创建时不需要命名,不需要显式地指定函数 ,所以叫匿名函数。

普通函数与匿名函数的对比:

普通函数

1
2
3
4
5
def add(a,b):
return a + b


print add(2,3)

匿名函数

1
2
3
add = lambda a,b : a + b

print add(2,3)

从上面看不出来本质的区别,匿名函数主要是和其它函数搭配使用:

1
2
3
4
res = map(lambda x: x ** 2, [1, 5, 7, 4, 8])

for i in res:
print(i)

执行后输出为:

1
2
3
4
5
1
25
49
16
64

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

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

1
2
3
4
5
6
>>> lbd = lambda x : x * x
>>> lbd
<function <lambda> at 0x0117D618>
>>> lbd(3)
9
>>>

同样,也可以把匿名函数作为返回值返回,比如:

1
2
3
4
5
def build(x, y):
return lambda: x * x + y * y


print(build(2, 3)())

递归函数

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

例如在计算阶乘 n! = 1 x 2 x 3 x ... x n ,用函数 fact(n) 表示 ,则 fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n ,所以 fact(n) 可以表示为 n x fact(n-1),只有 n=1 时需要特殊处理 :

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 1 x 2 x 3 x 4 x ... x n

def fact(n):
if n == 1:
return n
else:
return fact(n - 1) * n


print(fact(5))

计算 fact(5) 过程如下:

1
2
3
4
5
6
7
8
9
10
===> fact(5)
===> 5 * fact(4)
===> 5 * (4 * fact(3))
===> 5 * (4 * (3 * fact(2)))
===> 5 * (4 * (3 * (2 * fact(1))))
===> 5 * (4 * (3 * (2 * 1)))
===> 5 * (4 * (3 * 2))
===> 5 * (4 * 6)
===> 5 * 24
===> 120

使用循环的方式处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 1 x 2 x 3 x 4 x ... x n


def fact(n):
x = 1
for i in range(1, n + 1):
x *= i
return x


print(fact(5))

递归函数的优点:

  • 定义简单,逻辑清晰。理论上所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

递归函数的特性:

  • 必须要有一个特定的结束条件。

  • 每次进入更深一层递归时,问题规模相比上次递归都应有所减少。

  • 递归函数在很多情况下效率会很低,并且递归层次过多会导致栈溢出,堆栈扫盲

练习

练习一: 斐波那契数列(Fibonacci sequence ): 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ........

  • 定义一个函数,接收一个参数 n
  • 从第 3 项开始,每一项都等于前两项之和
  • 调用函数时返回第 n 项 的结果,例如 n = 8 时,对应的项是 21

循环法:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def fibo(n):
pre = 1 # 前一个数
lst = 1 # 后一个数
for i in range(2, n - 1): # 第一个值是固定的,循环到 n-1 即可得到 n 对应的值
pre, lst = lst, pre + lst
return pre + lst


print(fibo(8))

递归法:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python3
# -*- coding: utf-8 -*-


def fibo(n):
if n == 1 or n == 2:
return 1
return fibo(n - 2) + fibo(n - 1)


print(fibo(8))

练习二: 已知 t1, t2 = ('a', 'b'), ('c', 'd'),请使用 Python 中匿名函数生成列表 [{'a':'c'},{'b':'d'}]

1
2
3
4
5
6
7
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

t1, t2 = ('a', 'b'), ('c', 'd')

ls = list(map(lambda t: {t[0]: t[1]}, zip(t1, t2)))
ls2 = [{k: v} for k, v in zip(t1, t2)]
有钱任性,请我吃包辣条
0%