python基础(十八):函数式、递归调用

一、函数式

1、函数式简介

函数式编程并非用函数编程这么简单,而是将计算机的运算视为数学意义上的运算,比起面向过程,函数式更加注重的是执行结果而非执行的过程,代表语言有:Haskell、Erlang。而python并不是一门函数式编程语言,但是仍为我们提供了很多函数式编程好的特性,如lambda,map,reduce,filter

因为map、reduce,filter应用场景,都可以生成器生成式解决,而且三个函数式得到的都是生成器,因此我们学好生成器生成式就行了。

2、匿名函数与lambda

对比使用def关键字创建的是有名字的函数,使用lambda关键字创建则是没有名字的函数,即匿名函数,语法如下

lambda 参数1,参数2,...: expression

案例演示:

# 1、定义
lambda x,y,z:x+y+z

#等同于
def func(x,y,z):
    return x+y+z

# 2、调用
# 方式一:
res=(lambda x,y,z:x+y+z)(1,2,3)

# 方式二:
func=lambda x,y,z:x+y+z # “匿名”的本质就是要没有名字,所以此处为匿名函数指定名字是没有意义的
res=func(1,2,3)

匿名函数与有名函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,所以匿名函数用于临时使用一次的场景,匿名函数通常与其他函数配合使用,我们以下述字典为例来介绍它

salaries={
    'siry':3000,
    'tom':7000,
    'lili':10000,
    'jack':2000
}

要想取得薪水的最大值和最小值,我们可以使用内置函数max和min:

>>> max(salaries)
'tom'
>>> min(salaries)
'jack'

内置max和min括号中都应该传可迭代对象,工作原理都是迭代字典,取得是字典的键,因而比较的是键的最大和最小值,而我们想要的是比较值的最大值与最小值,于是做出如下改动

# 函数max会迭代字典salaries,每取出一个“人名”就会当做参数传给指定的匿名函数,然后将匿名函数的返回值当做比较依据,最终返回薪资最高的那个人的名字
>>> max(salaries,key=lambda k:salaries[k]) 
'lili'
# 原理同上
>>> min(salaries,key=lambda k:salaries[k])
'jack'

我们可以用sorted对该字典薪资排序:

sorted(salaries,key=lambda k:salaries[k],reverse = True) # ['lili', 'tom', 'siry', 'jack']
reverse = True #降序排序,默认值为False,升序排序!

二、递归调用

1、递归调用要点透析

函数不仅可以嵌套定义(闭包函数,作用值包给内部函数),还可以嵌套调用,即在调用一个函数的过程中,函数内部又调用另一个函数,而函数的递归调用指的是在调用一个函数的过程中又直接或间接地调用该函数本身

扫描二维码关注公众号,回复: 11227323 查看本文章
def f1():
    print('from f1')
    f1()
f1()
def f1():
    print('from f1')
    f2()

def f2():
    print('from f2')
    f1()

f1()

上面两个都属于递归调用,递归调用都是一个无限循环的过程,但在python对函数的递归调用的深度做了限制,因而并不会像大家所想的那样进入无限循环,会抛出异常,要避免出现这种情况,就必须让递归调用在满足某个特定条件下终止。

#1. 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可以使用
sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制

#2. python不是一门函数式编程语言,无法对递归进行尾递归优化。

2、递归调用的两个过程:回溯与递推

定义:

  • 回溯:每次向深层次进行不断调用,称之为回溯
  • 递推:回溯到某个层次,然后会停止,然后一层层的返回,这个过程称之为递推

用一个例子说明回溯与递归两个过程:

某公司四个员工坐在一起,问第四个人薪水,他说比第三个人多1000,问第三个人薪水,第他说比第二个人多1000,问第二个人薪水,他说比第一个人多1000,最后第一人说自己每月5000,请问第四个人的薪水是多少?
在这里插入图片描述代码实现:

def salary(n):
    if n==1:
        return 5000
    return salary(n-1)+1000

s=salary(4)
print(s)

3、递归经典例题练习

(1)嵌套多层的列表,要求打印出所有的元素
items=[[1,2],3,[4,[5,[6,7]]]]
def foo(items):
    for i in items:
        if isinstance(i,list): #满足未遍历完items以及if判断成立的条件时,一直进行递归调用
            foo(i) 
        else:
            print(i,end=' ')

foo(items) #打印结果1 2 3 4 5 6 7
(2)二分法递归实现
num = input('请输入您想要查询的数字:').strip()
num = int(num)
list1 = [1, 2, 3, 4, 5, 6, 8, 9, 10]
def binary_search(find_num,max=len(list1)-1,min = 0):
    mid = (min + max)//2
    if find_num > list1[max] or find_num < list1[min]: # 此处是找不到判断的条件!  
        print('查找的数字不存在!')
    elif list1[mid] < find_num:
        binary_search(find_num,min = mid + 1)
    elif list1[mid] > find_num:
        binary_search(find_num,max = mid - 1)
    else:
        print('find it',mid)
binary_search(num)

列表中找不到值时的判断条件,有人可能会认为条件少了,其实这两个条件就够了。因为列表中都是从小到大排序好了的,因此我先考虑find_num比列表中最大值还大,比最小值还小,那么查找的数字一定不在列表中,因此便有了这个:find_num > list1[max] or find_num < list1[min]

但是可能有人会问,在列表最大值和最小值中间,查找一个不存在的数,因此还需要添加条件,其实不然,查找不到,最后的情景一定是,min、max、mid一定指在一个数上,既然如此,find_num最后一定会满足find_num > list1[max] or find_num < list1[min]

猜你喜欢

转载自blog.csdn.net/weixin_44571270/article/details/106040990
今日推荐