美文网首页
递归函数遇到的一些坑

递归函数遇到的一些坑

作者: 阿登20 | 来源:发表于2021-04-04 14:23 被阅读0次

    递归遇到的一些坑。

    为什么递归函数会返回None

    def calc(n,count):
        '''
        :param n: 需要进行递归的对象
        :param count: 计数器
        :return: 条件不成立时,返回最终值
        '''
        # print(n,count)
        if count < 5: #运行第五次时退出
            calc(n//2,count+1) #每一层接收它下一层的值,return必不可少,否则倒数第三层无法接收倒数第二层的返回值
        else:
            return n  # 在上一个return 递归函数被中止
    f = calc(199,1)
    print('res运算第五次时的结果:',f) # 输出>>res运算第五次时的结果: 12
    
    def t(n):
        if n ==1:
            return n
        return t(n-1)   # 递归函数在 n=2在时候调用结束,这里不加return就会返回为None
    print(t(4))
    
    

    上面的例子:在调用递归处不加return 就会返回None.因为在递归结束处并没有返回值,所以默认返回None。当多加一个return是把下层的return返回回来,一层层返回,最后返回值才会是n

    再看一个求列表叠加的例子

    a = [1,5,7,9]
    def sum(a):
        if isinstance(a, list) and len(a) >1:
            # return a[0] +sum(a[1:])
            a[0] +sum(a[1:])
        else:
           return  a[0]
    
    如果注释处不加return 就会报错。因为递归处返回的是None None和int不能相加
    TypeError: unsupported operand type(s) for +: 'int' and 'NoneType'       
    

    1。 递归函数在for循环里面return,会结束for循环,所以不能在for循环里面return 递归函数 8行代码处。for循环自带递归 return

    a = [1,3,4,["啊登","向佳","咸维维",[66,77]],[[15,19,["香蕉",["西瓜","芒果"]]],8,0]]
    from collections.abc import Iterable
    # 1。 递归函数在for循环里面return,会结束for循环,所以不能在for循环里面return 递归函数 8行代码处。for循环自带递归 return
    def get_a(a):
        b = []
        for i  in a:
            if isinstance(i, Iterable) and (not isinstance(i, (str, bytes))): 
                return get_a(i)
                
            else:
                b.append(i)
        
        return b
    
      
    print(get_a(a))   [66, 77]
    

    可以发现 在for循环里面return 递归函数 最后得到的结果只有一组,以为 for循环遇到return终止了当前循环,比如a列表 [[15,19,["香蕉",["西瓜","芒果"]]]元素并没有循环到。那么怎么办呢? for 不加return呢?

    a = [1,3,4,["啊登","向佳","咸维维",[66,77]],[[15,19,["香蕉",["西瓜","芒果"]]],8,0]]
    def get_a(a):
        b = []
        for i  in a:
            if isinstance(i, Iterable) and (not isinstance(i, (str, bytes))):
                get_a(i)
            else:
                b.append(i)
        return b
    
    print(get_a(a)) [1, 3, 4]
    

    当调用get_a(i) 递归调用的时候,每一个列表for循环结束后会返回当前调用的返回值b,可以看出a对象里面有多个列表,那么递归调用就会返回多个返回值b. 这个每一次的返回值 并没有做整合处理。所以上面最后的返回值是 [1,3,4]

    当递归遍历想要所有的结果的时候,不能在for循环里面return 递归函数。 for循环结束后return 可以接受递归一次的返回值。如果递归的每一次结果都要叠加到一起可以这么做:

    1. 如果返回值可以叠加操作,可以用 res += 递归调用。
    2. 如果递归返回值是列表,可以 列表.extend(递归调用)
      • 还有一种的就从外表传参给个空列表传给函数,函数用一个变量去接收这个空别表。 在递归调用处直接这样调用。fo(x,当前列表) x是参数, 当前列表第一次值是传过来的空列表。

    案例1

    import os
    def count_dir_size(path):
        """"统计文件或者文件夹大小,返回的是字节"""
        count_size = 0
        if not os.path.isdir(path):
            return os.path.getsize(path)
        else:
            for f in os.listdir(path):
                new_path = os.path.join(path, f)
                if os.path.isfile(new_path):
                    count_size = count_size + os.path.getsize(new_path)
                else:
                    count_size = count_size + count_dir_size(new_path)
    
            return count_size
    

    案例2 取出列表a所有的元素,放在一个新列表里面

    a = [1,3,4,["啊登","向佳","咸维维",[66,77]],[[15,19,["香蕉",["西瓜","芒果"]]],8,0]]
    def get_a(a):
        b = []
        for i  in a:
            if isinstance(i, Iterable) and (not isinstance(i, (str, bytes))):
                b.extend(get_a(i))
            else:
                b.append(i)
        return b
    print(get_a(a))
    [1, 3, 4, '啊登', '向佳', '咸维维', 66, 77, 15, 19, '香蕉', '西瓜', '芒果', 8, 0]
    

    案例3 如果递归调用,对调用处不做任何处理,可以外部穿一个参数,比如空列表

    a = [1,3,4,["啊登","向佳","咸维维",[66,77]],[[15,19,["香蕉",["西瓜","芒果"]]],8,0]]
    def get_a(a,list_none):
        b = list_none
        for i  in a:
            if isinstance(i, Iterable) and (not isinstance(i, (str, bytes))):
    
                get_a(i, b)
            else:
                b.append(i)
        return b
    
    print(get_a(a, []))
    

    案例4 yield from 函数。去做处理

    a = [1,3,4,["啊登","向佳","咸维维",[66,77]],[[15,19,["香蕉",["西瓜","芒果"]]],8,0]]
    def get_a(a):
        for i  in a:
            if isinstance(i, Iterable) and (not isinstance(i, (str, bytes))):
                yield from get_a(i)
            else:
                yield i
    
    print(list(get_a(a)))
    

    相关文章

      网友评论

          本文标题:递归函数遇到的一些坑

          本文链接:https://www.haomeiwen.com/subject/tellkltx.html