匿名函数与函数递归

一、什么是匿名函数

  匿名函数就是没有名字的函数,又叫lambda表达式。用于一些简单的需要用函数去解决的问题,特点是只能在定义时使用一次,且函数体只有一行

  匿名函数的定义就相当于只产生一个变量的值,而没有绑定任何名字,所以会在定义完之后就被回收,无法重复使用,只能在定义时使用一次

二、为何要用匿名函数

  当某一个功能仅使用一次就没有再重复使用的必要了,就可以定义成匿名函数

三、匿名函数的应用

参数可以有多个,用逗号隔开,返回值和正常的函数一样可以是任意的数据类型

# 把下面的函数转换成匿名函数
def add(x, y):
    return x + y

s = add(5, 8)
print(s)

# 结果:
s = (lambda x, y: x + y)(5, 8)
print(s)
匿名函数的应用
# 取出最大工资对应的人名

salaries = {
    'qiu': 2000,
    'xi': 30000,
    'qiuxi': 2500,
    'rufeng': 3000
}

def func(k):
    return salaries[k]

print(max(salaries,key=func))   # xi

# 1. 将可迭代对象salaries变成迭代器对象iter_obj
# 2. next(iter_obj)得到一个人名,然后将该人名当作参数传给key指定的函数,然后调用函数将函数的返回值当作比较依据
# 3. 比较大小,取出最大值对应的人名

# 上面的函数还可以用匿名函数来实现
print(max(salaries, key=lambda k: salaries[k]))
# 同样,取出最小的使用函数min
print(min(salaries, key=lambda k: salaries[k]))
max函数与匿名函数
# 将所有人的工资大小排序,输出排序后的人名

salaries = {
    'qiu': 2000,
    'xi': 30000,
    'qiuxi': 2500,
    'rufeng': 3000
}

# 从大到小
print(sorted(salaries, key=lambda k: salaries[k], reverse=True))
# 从小到大
print(sorted(salaries, key=lambda k: salaries[k]))

# 运行后
['xi', 'rufeng', 'qiuxi', 'qiu']
['qiu', 'qiuxi', 'rufeng', 'xi']
sorted函数与匿名函数
# 为每个名字加上一串字符
names = ['qiu', 'xi', 'ru', 'feng']

# 手动实现
new_names = []
for name in names:
    new_names.append(name+'_nice')
print(new_names)

# 列表生成式
new_names = [name+'_nice' for name in names]
print(new_names)

# map+匿名函数
res = map(lambda x: x+'_nice', names)
print(res)  # Python3里会打印函数地址
print(list(res))

# 运行后
['qiu_nice', 'xi_nice', 'ru_nice', 'feng_nice']
['qiu_nice', 'xi_nice', 'ru_nice', 'feng_nice']
<map object at 0x0000012E7A848A90>
['qiu_nice', 'xi_nice', 'ru_nice', 'feng_nice']
map函数与匿名函数
# 1到100的求和

# 手动实现
res = 0
for i in range(101):
    res += i
print(res)

# 列表生成式
print(sum([i for i in range(101)]))

# reduce+匿名函数
from functools import reduce
print(reduce(lambda x, y: x + y, [i for i in range(101)]))

# 运行
5050
5050
5050
reduce函数和匿名函数
# 提取包含指定字符的元素并输出
names=['qiu_nice','xi_nice','ru_nice','feng']

# 方式一:手动实现
new_names = []
for name in names:
    if name.endswith('nice'):
        new_names.append(name)
print(new_names)

# 方式二:列表生成式
new_names = [name for name in names if name.endswith('nice')]
print(new_names)

# 方式三:filter+匿名函数
res = filter(lambda name: name.endswith('nice'),names)
print(res)      # Python3输出地址
print(list(res))

# 运行
['qiu_nice', 'xi_nice', 'ru_nice']
['qiu_nice', 'xi_nice', 'ru_nice']
<filter object at 0x000001DBBE8C8390>
['qiu_nice', 'xi_nice', 'ru_nice']
filter函数与匿名函数

四、什么是函数递归

  函数的递归调用是函数嵌套调用的一种特殊形式,即在调用一个函数的过程中又直接或者间接地调用了该函数本身

  递归本质就是一个循环的过程,但是递归必须满足两个原则:

    1、每进入下一层递归,问题的规模必须有所减少

    2、递归必须有一个明确的结束条件或者说有一个明确的进入下一层递归的条件

  并且递归有两个明确的阶段:

    1、回溯:一层一层的递归调用下去

    2、递推:在某一层结束掉递归,然后一层一层返回

五、为何要用递归

  在某些情况下,基于递归来使用重复的过程比循环更加简单

六、递归的使用

1、猜年龄

  小明是新来的同学,丽丽问他多少岁了。他说:我不告诉你,但是我比滔滔大两岁。滔滔说:我也不告诉你,我比晓晓大两岁。晓晓说:我也不告诉你,我比小星大两岁。小星也没有告诉他,说:我比小华大两岁。最后小华说,我告诉你,我今年18岁了

这个怎么办呢?当然,有人会说,这个很简单啊,知道小华的,就会知道小星的,知道小星的就会知道晓晓的,以此类推,就会知道小明的年龄啦。这个过程已经非常接近递归的思想了。

小华 18
小星 18+2
晓晓 20+2
滔滔 22+2
小明 24+2
age(5) = age(4)+2
age(4) = age(3) + 2 
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 18
def calc_age(n):
    if n == 1:
        return 18
    else:
        return calc_age(n-1)+2

print(calc_age(5)) # 26
代码实现

2、取元素

  给定一个嵌套列表,取出列表中的每个元素输出打印

  li = [1, [2, [3, [4, [5, [6, [7, [8, [9, ]]]]]]]]]

li = [1, [2, [3, [4, [5, [6, [7, [8, [9, ]]]]]]]]]
def func(l):
    for i in l:
        if type(i) is list:
            func(i)
        else:
            print(i)

func(li)
代码实现

七、二分法查找

假设要在电话簿中找一个名字以K打头的人,可以从头开始翻页,直到进入以K打头的部分。但你很可能不这样做,而是从中间开始,因为你知道以K打头的名字在电话簿中间。这是一个查找问题,可以使用二分查找算法来解决。而算法就是一组完成任务的指令,是高效解决问题的一种思路。

假设我从1到100随便想一个数字,你的目标是以最少的次数猜到这个数字。你每次猜测后,我会说小了、大了或对了。假设你从1开始依次往上猜,每次加一个数,这样每次猜测都只能排除一个数字。如果我想的数字是99,你得猜99次才能猜到!这是简单查找,更准确的说法是傻找,这显然是一种糟糕的猜数法。

假设你从50开始猜,如果小了,排除了一半的数字!至此,你知道1~50都小了。接下来,你猜75,大了,那余下的数字又排除了一半!!使用二分查找时,你猜测的是中间的数字,从而每次都将余下的数字排除一半。接下来,你猜63(50和75中间的数字),大了,猜57,对了,这就是二分查找。不管我心里想的是哪个数字,你在7次之内都能猜到,因为每次猜测都将排除很多数字!

使用二分查找时,每次都排除一半的数字

使用二分法,数字列表是有序的

# 从小到大排列的数字列表
nums = [1, 13, 15, 23, 27, 31, 33, 57, 73, 81, 93, 94, 97, 101]
def binary_search(find_num,nums):
    if len(nums) == 0:
        print('不存在')
        return
    mid_index = len(nums) // 2
    if find_num > nums[mid_index]:
        # 在右边
        nums = nums[mid_index + 1:]
        binary_search(find_num, nums)
    elif find_num < nums[mid_index]:
        # 在左边
        nums = nums[:mid_index]
        binary_search(find_num, nums)
    else:
        print('找到了')

binary_search(97, nums)
代码实现
原文地址:https://www.cnblogs.com/qiuxirufeng/p/9766307.html