函数进阶——函数递归调用、生成式

130、函数式接口function 一、Function<T, R> 接口用来将一个类型数据T转换为数据类型R,当然T和R的类型可以一致。 源码如下: @FunctionalInterface public interface Function<T, R> { R apply(T t); /** * @return a c... 阅读详情

函数递归调用

​ 函数递归调用就是指在调用一个函数的过程中,又直接或者间接的调用了该函数本身,这种调用就称做“函数的递归调用“。

  • 直接调用函数本身:调用func1的过程中又调用了func1.

    count = 1
    def func1():
        print('from index')
        global count
        count += 1
        print(count)
        func1()
        
    index()
    

    图解:

    image-20220111211336095

  • 间接调用函数本身:在调用func1的过程中,会调用func2,在调用func2的过程中又会调用func1.

    def func1():
        print('from func1')
        func2()
        
    def func2():
        print('from func2')
        func1()
        
    func1()
    

    图解:

    image-20220111211710988

  • 函数的递归调用,如果不设置结束条件是会无限循环下去的,这样会抛出异常,为了避免,因此要设定在满足某种条件下就终止。

补充:系统默认递归调用深度为1000次,但是我们可以通过系统的方法来修改和查看递归调用深度。

  • 查看递归调用的默认深度

    import sys
    
    print(sys.getrecursionlimit())  # 1000
    
  • 修改递归调用的默认深度

    import sys
    
    print(sys.getrecursionlimit())  # 修改前为1000
    sys.setrecursionlimit(2000)
    print(sys.getrecursionlimit())  # 修改后为2000
    
回溯与递推

引例:老师问四个学生1,2,3,4的考试成绩,学生4说自己的成绩比学生3高10分,学生3说自己的成绩比学生2高10分,学生2说自己的成绩比学生1高10分,学生1说自己的成绩为66分,请问学生1,2,3,4四个学生的成绩分别为多少?

分析:要想知道学生4的成绩就得知道学生3的成绩,要想知道学生3的成绩就得知道学生2的成绩,以此类推,我们可以得到下面的表达式:

score(4) = score(3) + 10
score(3) = score(2) + 10
score(2) = score(1) + 10
score(1) = 66

结论: score(n) = score(n-1) + 10

代码实现:

def score(n):
    if n == 1:
        return 66
    return score(n-1) + 10

print(score(4))  # 96

总结:我们将从学生4成绩的得出过程,通过推导,找到学生1成绩(也就是终止条件)的过程称为“回溯”;将通过学生1的成绩推导学生4的成绩的过程称为“递推”。

图解:

image-20220111215239994

练习题:逐个打印列表l中的值:l = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]

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

# 第一种方式:
# 第一种方式:
for i in l:
    if type(i) is int:
        print(i)
    else:
        # 说明当前循环的数据类型是列表
        for j in i:
            # 判断j是什么类型
            if type(j) is int:
                print(j)
            else:
                # 说明当前循环的数据类型是列表
                for k in j:
                    if type(k) is int:
                        print(k)
                    else:
                        # 说明当前循环的数据类型是列表
                        for x in k:
                            if type(x) is int:
                                print(x)
                            ...

# 很显然方式一的代码重复很多,因此我们采用函数递归的方式


# 第二种方式:函数递归调用
def get_num(l):
    for i in l:
        if type(i) is int:
            print(i)
        else:
            get_num(i)
get_num(l)

三元表达式

​ 三元表达式是python对于if双分支结构的一种代码简化。

  • 传统写法
def my_max(a, b):
    if a > b:
        return a
    else:
        return b

print(my_max(1, 2))
  • 使用三元表达式写法
a = 1111
b = 211
res = a if a > b else b  
print(res)
# 本质就是传统的写法,只是对代码进行简化

练习题:

a = 1111
b = 2111
username = 'mark'
res = a if a > b else ('world' if False else ('靓仔' if username == 'mark' else '小伙子'))
print(res)

# 让用户输入判断
cmd = input('username:').strip()
res = '靓仔' if cmd == 'mark' else '小伙子'
print(res)

列表生成式

​ 列表生成式是python对于生成列表的方式,是简化代码的解决方案。

  • 传统写法:
# 题目:生成一个新列表,内容为愿列表中所有元素拼接plus字符串
phone_list = ['huawei', 'vivo', 'iphone']

new_phone_list = []
for i in phone_list:
    new_phone_list.append(i +'plus')

print(new_phone_list)
  • 使用列表生成式:
new_phone_list = [i + 'plus' for i in phone_list]
print(new_phone_list)

练习:为列表中的元素为’huawei’的元素添加plus,其余元素添加 ’++‘

# 传统写法:
new_phone_list = []
for i in phone_list:
    if i != 'huawei':
        new_phone_list.append(i+'++')
    else:
        new_phone_list.append(i + 'plus')

# 列表生成式实现:
new_phone_list = [i + '++' if i != 'huawei' else i + 'plus' for i in phone_list]
print(new_phone_list)

字典生成式、集合生成式、生成器

l1 = ['name', 'age', 'hobby']
l2 = ['mark', 18, 'music']

# 传统写法:
new_dict = {}
for i in range(len(l1)):
    new_dict[l1[i]] = l2[i]

print(new_dict)


# 字典生成式
res = {l1[i]: l2[i] for i, j in enumerate(l1)}
print(res)
# 执行结果:{'name': 'mark', 'age': 18, 'hobby': 'music'}

# 集合生成式
res = {l1[i] for i, j in enumerate(l1)}
print(res)
# 执行结果:{'hobby', 'age', 'name'}

# 生成器
res = (l1[i] for i, j in enumerate(l1))
print(res)
# 执行结果:<generator object <genexpr> at 0x000001C2687A5F90> 表示一个生成器对象,通过next()方法来生成元素
print(next(res))
# name

补充:

# 枚举
l1 = ['name', 'age', 'hobby']
for i,j in enumerate(l1, start=2):
    print(i,j)
    
# 执行结果:
2 name
3 age
4 hobby

匿名函数

​ 即没有名字的函数。

  • 语法格式:

    lambda 参数:返回值
    
  • 示例:

    def index(x):
        return x ** 2
    
    print(index)
    print((lambda x:x**2)(2))  
    
    res = lambda x:x**2
    print(res(2))
    
    # 但目的不是这样用的,一般情况下不会单独使用匿名函数
    # 会结合一些内置函数来使用
    
    # map函数
    l = [1, 2, 3, 4, 5, 6]
    res=list(map(lambda x:x**3, l))
    print(res)
    
    # 执行结果:[1, 8, 27, 64, 125, 216]
    

算法之二分法

​ 二分法查找相比较与for循环来讲,查找效率大大提升,这就体现出了算法的优越性。

  • 前提条件:列表有序
  • 示例:查找元素66,返回是否找到
l = [1, 2, 3, 4, 5, 6, 11, 22, 34, 44, 55, 66, 67, 333, 444]

# 方式一:for循环查找,挨个比对,需要在进行第12次比对结果才会停止
for i in l:
    if i == 66:
        print('找到了')
        break

        
# 方式二:利用二分法查找,递归两次就可结束,效率大大提升
# 1. 先进行排序
l.sort()

def my_half(target_num, l):
    # 1. 从列表中去一个中间值
    middle_index = len(l) // 2

    # 2. 比较
    if target_num > l[middle_index]:
        # 要找的元素在右边
        l_right = l[middle_index + 1:]
        my_half(target_num, l_right)
        print(l_right)
    elif target_num < l[middle_index]:
        # 要找的元素一定在左边
        l_left = l[:middle_index]
        my_half(target_num, l_left)
        print(l_left)
    else:
        print('找到了,哈哈哈哈')

my_half(66,l)
函数递归调用详解 递归问题是一个说简单也简单,说难也有点难理解的问题.我想非常有必要对其做一个总结. 首先理解一下递归的定义,递归就是直接或间接的调用自身.而至于什么时候要用到递归,递归和非递归又有那些区别?又是一个不太容易掌握的问题,更难的是对于递归调用的理解.下面我们就从程序+图形的角度对递归做一个全面的阐述. 我们从常见到的递归问题开始: 1 阶乘函数 #include using names 阅读详情

相关推荐

函数递归调用

微信公众号搜索【程序媛小庄】,关注半路出家的程序媛如何靠python开发养家糊口~ 引入 函数既可以嵌套定义也可以嵌套调用。嵌套定义指的是在定义一个函数时在该函数内部定义另一个函数;嵌套调用指的是在调用一个函数的过程中函数内部有调用另一个函数。而函数的递归调用指的是在调用一个函数的过程中又直接或者间接的调用该函数本身。 函数递归介绍 函数递归就是函数的递归调用,是函数嵌套调用的一种特殊形式,具体就是指在调用一个函数的过程中直接或者间接的调用到本身,递归的本质就是循环做重复的事情。 在调用func的过程中.

demon_or_angle的博客 2344

深入理解计算机系统

csapp的过程反汇编....

m0_60284775的博客 2036

保姆级教程:用YOLOv5s搞定钢材表面缺陷检测,从数据集NEU-DET到模型部署全流程

本文提供了一份详细的YOLOv5s钢材表面缺陷检测教程,涵盖从NEU-DET数据集处理到模型部署的全流程。针对工业环境中的实际限制,如计算资源有限和标注样本少等问题,提供了优化方案和实用技巧,帮助开发者快速实现高效的钢材缺陷检测系统。

weixin_30568591的博客 465

函数指针

学习了数组之后,我们知道数组是在内存中申请一块内存空间;数组名代表内存块的首地址,通过数组名可以访问内存块中的数据。 那么,对于函数,它也是存放在内存块中的一段数据。例如下面的函数: voidfunc(inta) { printf("in func, a = %d\n", a); } 此时,定义了一个函数名是func的函数。可以如下调用该函数: func(100); 此时,就进入了func函数的函数体中执行。可以看到,函数名如同数组名一样,代表函数所在内存块的首地址。通过数组名可以访问数..

LC的专栏 552

海康威视国内版监控设备改英文界面难题:原因解析与解决方案

跨境安防设备部署中,国内采购的海康威视监控设备常因仅支持中文界面导致海外用户无法操作。本文剖析了该问题的核心原因:海康威视对国内版和海外版设备实行区域锁定策略,国内版固件仅内置中文且无法通过常规方式切换语言。针对此问题,文章提供了三种解决方案:1)官方合规的海外版固件更换;2)低成本的操作界面翻译与远程协助;3)长期更换海外版设备的彻底解决方案。同时给出了跨境采购的注意事项,强调应提前确认设备版本、拒绝非官方改造并预留适配时间。

海康威视技术支持 3954

告别CPU空转!用STC8的SPI+DMA高效驱动上百颗WS2812B灯珠

本文详细解析了如何利用STC8单片机的SPI+DMA外设高效驱动WS2812B全彩灯珠,解决传统软件延时驱动方式在长灯带应用中的性能瓶颈。通过硬件方案设计、数据格式转换和DMA传输配置,实现高达400Hz的刷新率和低于5%的CPU占用率,适用于大规模灯光项目。

weixin_30847939的博客 396

遗传算法解决实际例的学习笔记

总结起来,这段代码的循环逻辑是从种群中选择相邻的两条染色体,根据交叉概率和随机生成的二进制序列,对这两条染色体的指定基因位置进行交叉操作。循环的步长为2,确保选择的染色体是相邻的。总结起来,这段代码是对种群中的每个染色体进行遍历,将其二进制编码转换为十进制数值,并解码到函数定义域内,然后计算解码后染色体的适应度。首先,先把它们加起来,然后每个适应度值去除以总和,就是占比的概率,概率越大表示被选中的概率越高。上面代码的意思就是,创建1X100列的矩阵,每一列代表那一代的适应度最高的函数值。

weixin_60734616的博客 635

避坑指南:C#用S7NetPlus读写西门子PLC字符串(String/WString)的完整方案

本文详细解析了C#通过S7NetPlus读写西门子PLC字符串(String/WString)的完整方案,包括内存布局、编码差异和字节序处理等关键技术细节。提供了实战优化的代码示例和常见问题排查指南,帮助开发者避免乱码、截断等常见陷阱,提升工业自动化项目的开发效率。

weixin_32956805的博客 321

C语言学习笔记:函数的递归

首先我们声明了两个函数 func1 和 func2 分别采用不同的方法,func1 返回一个整型变量,我们直接赋值为6,省略判断步骤,func1需要一个for循环来解决这个计算,而func2,他的返回值是一个三元运算,只需要一行就可以完成计算需求。观察func2就可以发现,在将3赋值给n时,会进行第一次三元运算,判断 n是否大于1,n=3,则n*func2(n-1),这时再次调用func2函数,形参就变成了2,然后再次判断后进入三元运算,这时n=1,返回值为3*2。函数是构成c语言的基本单元;

2301_80548884的博客 662

GD32F470实战:如何用EXMC+SDRAM搞定LVGL大内存需求(附完整代码)

本文详细介绍了如何在GD32F470微控制器上通过EXMC接口驱动外部SDRAM,以满足LVGL图形库的大内存需求。内容涵盖硬件连接、EXMC时序配置、轻量级内存管理器实现,以及将LVGL帧缓冲和资源无缝集成到SDRAM的实战方法,并提供了完整的代码示例和调试技巧,帮助开发者构建稳定可靠的嵌入式GUI系统。

k9l0m1的博客 442

直流无刷电机FOC控制算法 理论到实践 —— 理论(二)

在上一章节,我们对于FOC大体有了一个介绍,本博文将详细描述有关Clark变化、Park变化、反Park变化以及SVPWM的理论实现原理,也即相关数学运算实现。

爱出名的狗腿子 1万+

函数的递归调用

在调用一个函数的过程中又出现直接或间接的调用该函数本身,称为函数的递归调用。 直接:在调用函数f的过程中又要调用f函数。 (简单来说在一个函数定义里面又使用了该函数,而一般用到递归调用都包含一种类似递增递乘的有规律的变化。) ...

qq_60987125的博客 1万+

华为OD新系统机试真题 - 操作历史管理器的撤销/重做能力

华为OD机试新系统真题【操作历史管理器的撤销/重做能力】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【操作历史管理器的撤销/重做能力】

qq_45776114的博客 865

python函数的递归调用

函数递归就是函数的递归调用,是函数嵌套调用的一种特殊形式,具体就是指在调用一个函数的过程中直接或者间接的调用到本身,递归的本质就是循环做重复的事情。在调用func的过程中又调用func,这就是直接调用函数本身;在调用func的过程中调用foo,而在调用foo的过程中又调用func,这就是间接调用func本身。通过上面的分析,两种情况下的函数递归调用都是一个无限循环的过程,Python为了防止函数递归进入无限循环对函数递归调用的深度做了限制,一旦超出限制就会抛出异常。

weixin_71807218的博客 2069

Label Studio 数据标注平台,大模型预训练与微调必备

摘要:LabelStudio是一款开源数据标注工具,支持文本、图像等多种数据类型的标注。本文介绍了其安装方法(通过conda创建环境并pip安装)、基础使用流程(创建项目、导入数据、设置标签、标注导出)以及AI自动标注功能的实现。重点讲解了如何通过MLBackend集成LangChain模型实现自动标注:创建自定义模型类、构建预测链、处理返回结果,最后配置到LabelStudio项目中。该功能可显著提升标注效率,标注人员只需在AI预测结果基础上进行修正。

技术引领业务创新 290

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

函数递归调用?看这文就够了!

作者| Cooper Song 责编 | Elle 出品 | 程序人生(ID:coder_life) 我猜,大多数程序员第一次接触函数的递归调用都是在算斐波那契数列某项值的时候,这是函数递归调用最常见的应用之一。规定第一项和第二项为1,后面的项,每一项都是其前面两项的和。 用公式表示就是f(n)=f(n-2)+f(n-1)。 而进一步转化,就是f(n)=[f(n-2-2)+f(n...

程序人生的博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Python函数的递归调用

一:递归的定义 函数的递归调用:是函数嵌套调用的一种特殊形式 具体是指:在调用一个函数的过程当中,又直接或者间接地调用到了本身 Python对递归调用循环调用的次数有限制,为1000次 1.调用的例子: 直接调用本身 def f1(): print('是我') f1() f1() 间接调用本身 def f1(): print('我是f1') f2() def f2(): print('我是f12') f1() f1() 2.一段代码的循环运行方案有2

python学习者的博客 6185

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

函数的嵌套调用和递归调用

1.嵌套调用 如果函数1调用了函数2,函数2再调用了函数3,便形成了函数的嵌套调用。 例如: #include &amp;lt;iostream&amp;gt; using namespace std; int fun2(int m) { return m*m; } int fun1(int x,int y) { return fun2(x)+fun2(y); } int main(){ ...

elinice 7164

C语言函数之递归调用

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言函数的调用函数的递归调用中间递归函数多层递归函数递归函数的最大缺陷二、使用步骤1.引入库2.读入数据总结 前言 函数是学习C语言的最重要知识点之一,要学好这门编程语言,那么函数当然是至关重要的 提示:以下是本篇文章正文内容,下面案例可供参考 函数的调用 函数的递归调用 中间递归函数 多层递归函数 递归函数的最大缺陷 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。 二、使用步骤 1.引

qq_56870066的博客 5984

matlab函数的递归调用

matlab函数的递归调用 1、求n的阶乘 函数文件fact.m function f=fact (n) if n<=1 f=1; else f=fact (n-1)*n; end 脚本文件a.m n=input('Please input n='); s=fact (n); disp(s) 2、斐波拉契数列 Fibonacci数列定义如下: f1=1 f2=1 fn=fn-...

Heria_Yu的博客 1万+

函数的使用之递归调用

在前面的几篇文章中,我们了解并使用了一些函数的基本用法,但函数除了能够被主函数调用以外,其实还能被自己或是其他的函数调用,而这种特殊的用法就是我们今天讲到的——函数的递归调用。

Lin050421的博客 4934

函数的嵌套调用与递归调用

函数的嵌套调用与递归调用 实现C语言求a的n次方

ChengYuanCY的博客 4589

JS进阶 - 什么是 尾调用、尾递归、蹦床函数

标签: JS进阶 JS函数进阶相关,为 尾调用 尾回调 蹦床函数 做个笔记 具体的可以看 阮一峰 ECMAScript 6 入门 函数的扩展 文章目录尾调用尾调用通俗解释尾调用的意义尾递归蹦床函数(trampoline)尾递归优化实现 尾调用 尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。 最简单的尾调用实现...

Jioho的博客 2482
上一篇: 函数进阶——装饰器
下一篇: 函数进阶——内置方法补充、可迭代对象及迭代器对象
Jakey_src
博客等级 码龄9年 10粉丝 41原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值