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

下面是小凰凰的简介,看下吧!
💗人生态度:珍惜时间,渴望学习,热爱音乐,把握命运,享受生活
💗学习技能:网络 -> 云计算运维 -> python全栈( 当前正在学习中)
💗您的点赞、收藏、关注是对博主创作的最大鼓励,在此谢过!
有相关技能问题可以写在下方评论区,我们一起学习,一起进步。
后期会不断更新python全栈学习笔记,秉着质量博文为原则,写好每一篇博文。

一、函数式

1、函数式简介

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

map(func,seq)函数接收两个参数,一个是函数,一个是Iterable(可迭代对象,序列),map将传入的函数func()依次作用到序列seq的每个元素,并把结果作为新的Iterator(迭代器)返回,之后可转为lis或其他类型t输出。

r = map(lambda x:x*x, [ 1, 2, 3, 4, 5, 6 ])
print(list(r)) # [1,4,9,16,25,36]
# 由于结果r是Iterator(惰性序列),因此通过list()函数计算整个序列
4、reduce()

reduce(func,seq)把一个函数作用在一个序列[x1, x2, x3, …]上,这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算,返回的是一个数,累加和或者累乘结果

意即一次取序列两个元素放到函数,函数结果和下一个函数结果(取下两个元素放到函数得到的函数结果)相加,依次类推。

from functools import reduce
>>> l = [1,2,3,4,5,6,7,8,9]
>>> x = reduce(lambda x,y:x*y,l) # 改成x+y,就变成累加运算了!
>>> print(x)
362880
5、filter()

filter(func,seq)函数用于过滤序列,调用一个布尔函数func()来迭代遍历每个seq中的元素,返回一个Iterator(迭代器),里面存的是使func返回值为True的元素

和map()类似,filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

筛选回文 回文数是指从左向右读和从右向左读都是一样的数

# 找0到100的回文数
x = filter(lambda n:str(n)==str(n)[::-1],range(0,101))
print(list(x))
6、sorted

排序的核心是比较两个元素的大小。如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。

sorted(seq,key=func)函数也是一个高阶函数,它可以接收一个key函数来实现自定义的排序

# 按年龄排序:
>>> user_list = [{'name':'haha','age':15},{'name':'heihei','age':16}]
>>> 
>>> sorted(user_list,key=lambda l:l['age'],reverse=True)
[{'name': 'heihei', 'age': 16}, {'name': 'haha', 'age': 15}]

二、递归调用

1、递归调用要点透析

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

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]

  • 7
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凤求凰的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值