python3 递归函数

我还是那个在家带孩子的伪测试


学习笔记

  1. 如果一个函数在函数体重调用自身,那么这个函数就是递归函数
  2. 递归函数的优点是定义简单,逻辑清楚
  3. 使用递归函数需要注意防止栈溢出,在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧,由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
  4. 尾递归是指,在函数返回的时候,调用函数自己,并且,return语句不能包含表达式=>这是一个表达式:return n*fun(n-1),应该return fun(n-1)
  5. 解决栈溢出的办法是通过尾递归优化,这样编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
  6. 遗憾,遗憾,遗憾:大多数编程语言没有针对尾递归做优化,python解释器也没有优化,所以,即使将python的递归函数进行优化,也会存在栈溢出的情况

code

# 例子1:实现一个递归函数:计算n!=1*2*3*4*------*n
def fact(n):
    if n == 1:
        return 1
    else:
        return n * fact(n-1)
# 例子2:实现一个递归函数:对传入的dict进行key去重操作,将结果放到传入的set对象中
def dict_to_set(dict_ob,set_ob):
    for key, value in dict_ob.items():
        set_ob.add(key)
        if isinstance(value, dict):
            dict_to_set(value, set_ob)
        elif isinstance(value, list):
            for li in value:
                dict_to_set(li,set_ob)
    return set_ob
if __name__ == "__main__":
    dict01 = {"name":"ting","pass":"123","family":[{"name":"tian","age":1},{"name":"zhou","age":26}]}
    my_set = set()
    print(dict_to_set(dict01,my_set)) # 结果:{'name', 'pass', 'family', 'age'}

这里我记录一个坑,昨天我就掉进去了(怪我太无知),不过,大家可以跟着我的节奏,来写一个错误递归,看看效果

# 例子3:这是一个错误的递归,正确的方法参考例子2
def dict_to_set(dict_ob,set_ob):
    for key, value in dict_ob.items():
        set_ob.add(key)
        if isinstance(value, dict):
            return dict_to_set(value, set_ob)
        elif isinstance(value, list):
            for li in value:
                return dict_to_set(li,set_ob)
    return set_ob
if __name__ == "__main__":
    # 结果:异常
    dict01 = {"name":"ting","pass":"123","family":[{"name":"tian","age":1},{"name":"zhou","age":26}],"friend":[{"name":"yaya","age":21]},{"name":"ayu","age":12}}
    my_set = set()
    print(dict_to_set(dict01,my_set))

解释: 我们第一个例子中,调用本身是使用了return关键字,而后面的例子中,我们有使用了for循环,是不可以使用return dict_to_set()的,因为一旦return之后,for循环没有执行完的是不会继续执行的。

写在最后的话

真尴尬,我昨天写这几行代码花了我1个小时,本来想请教我家那位的,可是让我自己想办法解决,不然永远不会,我觉得说得在理,好在我还是写出来了。

你可能感兴趣的:(python3 递归函数)