首页 > 其他分享 >函数递归

函数递归

时间:2023-05-07 20:11:05浏览次数:33  
标签:salary f1 调用 函数 递归 薪水 1000

函数递归调用介绍

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

例如

在调用f1的过程中,又调用f1,这就是直接调用函数f1本身

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

在调用f1的过程中,又调用f2,而在调用f2的过程中又调用f1,这就是间接调用函数f1本身

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

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

提示:

#1. 可以使用sys.getrecursionlimit()去查看递归深度,默认值为1000,虽然可以使用
sys.setrecursionlimit()去设定该值,但仍受限于主机操作系统栈大小的限制
#2. python不是一门函数式编程语言,无法对递归进行尾递归优化。

回溯与递推

下面我们用一个浅显的例子,为了让读者阐释递归的原理和使用:

例4.5

某公司四个员工坐在一起,问第四个人薪水,他说比第三个人多1000,问第三个人薪水,第他说比第二个人多1000,问第二个人薪水,他说比第一个人多1000,最后第一人说自己每月5000,请问第四个人的薪水是多少?

思路解析:

要知道第四个人的月薪,就必须知道第三个人的,第三个人的又取决于第二个人的,第二个人的又取决于第一个人的,而且每一个员工都比前一个多一千,数学表达式即:

salary(4)=salary(3)+1000
salary(3)=salary(2)+1000
salary(2)=salary(1)+1000
salary(1)=5000
总结为:
salary(n)=salary(n-1)+1000 (n>1)
salary(1)=5000 (n=1)

很明显这是一个递归的过程,可以将该过程分为两个阶段:回溯和递推。

在回溯阶段,要求第n个员工的薪水,需要回溯得到(n-1)个员工的薪水,以此类推,直到得到第一个员工的薪水,此时,salary(1)已知,因而不必再向前回溯了。然后进入递推阶段:从第一个员工的薪水可以推算出第二个员工的薪水(6000),从第二个员工的薪水可以推算出第三个员工的薪水(7000),以此类推,一直推算出第第四个员工的薪水(8000)为止,递归结束。需要注意的一点是,递归一定要有一个结束条件,这里n=1就是结束条件。

代码实现:

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

执行结果:

8000

程序分析:

在未满足n1的条件时,一直进行递归调用,即一直回溯,见图4.3的左半部分。而在满足n1的条件时,终止递归调用,即结束回溯,从而进入递推阶段,依次推导直到得到最终的结果。

递归本质就是在做重复的事情,所以理论上递归可以解决的问题循环也都可以解决,只不过在某些情况下,使用递归会更容易实现,比如有一个嵌套多层的列表,要求打印出所有的元素,代码实现如下

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

使用递归,我们只需要分析出要重复执行的代码逻辑,然后提取进入下一次递归调用的条件或者说递归结束的条件即可,代码实现起来简洁清晰

标签:salary,f1,调用,函数,递归,薪水,1000
From: https://www.cnblogs.com/ycmyay/p/17380021.html

相关文章

  • 函数基本使用
    引入基于前一部分的学习,我们已经能开发一些功能简单的小程序了,但随着程序功能的增多,代码量随之增大,此时仍不加区分地把所有功能的实现代码放到一起,将会使得程序的组织结构不清晰,可读性变差,且程序中需要频繁使用同一功能时,只能重复编写该功能的实现代码,日积月累,程序将变得冗长,并且......
  • 函数模板和类模板2
    一.问题描述:复数类Complex有两个数据成员:a和b,分别代表复数的实部和虚部,并有若干构造函数和一个重载-(减号,用于计算两个复数的距离)的成员函数。要求设计一个函数模板template<classT>doubledist(Ta,Tb)对int,float,Complex或者其他类型的数据,返回两个数据的间距。以上......
  • 函数的参数
    形参与实参介绍函数的参数分为形式参数和实际参数,简称形参和实参:形参即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。实参即在调用函数时,括号内传入的值,值可以是常量、变量、表达式或三者的组合:#1:实参是常量res=my_min(1,2)#2:实参是变量......
  • 常用工具函数
    日常开发中,面对各种不同的需求,我们经常会用到以前开发过的一些工具函数,把这些工具函数收集起来,将大大提高我们的开发效率。1、校验数据类型exportconsttypeOf=function(obj){returnObject.prototype.toString.call(obj).slice(8,-1).toLowerCase()}示例:typeOf('......
  • Pandas内置函数方法
    1.导入数据:pd.read_csv(filename):从CSV文件导入数据pd.read_table(filename):从限定分隔符的文本文件导入数据pd.read_excel(filename):从Excel文件导入数据pd.read_sql(query,connection_object):从SQL表/库导入数据pd.read_json(json_string):从JSON格式的字符......
  • AF_DataRequest函数 解读
    目录作用原型参数解析afAddrType_t*dstAddrendPointDesc_t*srcEPSimpleDescriptionFormat_tafNetworkLatencyReq_tcIDlen*buf*transIDoptionsradius返回值函数定义作用Z-Stack中发送数据通过在应用层调用函数voidSampleApp_SendFlashMessage(uint16flashTime)完成,其中fla......
  • C++虚函数详解:多态性实现原理及其在面向对象编程中的应用
    在面向对象的编程中,多态性是一个非常重要的概念。多态性意味着在不同的上下文中使用同一对象时,可以产生不同的行为。C++是一种面向对象的编程语言,在C++中,虚函数是实现多态性的关键什么是虚函数虚函数是一个在基类中声明的函数,它可以被子类重写并提供不同的实现。在C++中,使用关......
  • pycharm内置函数怎么就一个pass
    仔细观察该文件的目录就会发现这个文件是PyCharm自己生成的,并没有定位到Python安装目录下Lib文件夹中的某个文件python的内置函数都是内嵌在解释器里面的,是使用C编写的,正常情况下你是无法查看的,只不过pycharm这种智能编辑器对其进行了一个抽象罢了所以python内置函数只有一个pass,......
  • spring 第一个例子-mian函数-03
     packagecom.sz.model;importorg.springframework.context.ApplicationContext;importorg.springframework.context.support.ClassPathXmlApplicationContext;publicclasstestMain{publicstaticvoidmain(String[]args){//创建Spring上下文(加载bean.xml)......
  • 类静态成员函数显式具体化的编译警告
    本文描述了在定义类的静态成员函数模板的显式具体化时出现的一个编译警告问题,并在解释其原因后给出了对应的解决办法。◆问题环境:macOSMojave(版本10.14.6),clang-1001.0.46.4(-std=c++11)头文件中定义了类的静态成员函数模板的显式具体化,代码编译没有出错,但出现如下警......