首页 > 解决方案 > 从 python 中打印非类型对象的方法返回的最后一个列表

问题描述

我有一个递归算法,它需要能够返回列表列表。

如果我打印剩余的列表,我会得到许多不同的列表,直到我们到达最后一个。那么我无法返回最后一个列表。

这是我的代码:

def subset_sum(numbers, target, partial=[], result = []):
    s = sum(partial)

    # check if the partial sum is equals to target
    if s == target:
        result.append(partial)
    if s >= target and len(numbers) == 1:
        print(result)
        print(type(result))
        return result

    for i in range(len(numbers)):
        n = numbers[i]
        remaining = numbers[i+1:]
        subset_sum(remaining, target, partial + [n], result)


if __name__ == "__main__":
    print(subset_sum([3,9,8,4,5,7,10],15))

这是输出:

[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]                                                                      
<class 'list'>                                                          
[]            

(ETC)

<class 'list'>
[[3, 8, 4], [3, 5, 7], [8, 7]]
<class 'list'>
[[3, 8, 4], [3, 5, 7], [8, 7]]
<class 'list'>
None

正如您所看到的,它确实做了我想要它做的事情,即使它在最后生成了一个列表,它也无法返回。

反正。预先感谢您的帮助。感谢所有帮助:)

标签: python

解决方案


语句仅将return其值返回给调用范围。嵌套函数调用时,如果所有中间函数也一样,叶子函数只能向根返回值return

>>> def do_return(call, *args):
...     return call(*args)

>>> def donot_return(call, *args):
...     call(*args)
...
>>> do_return(do_return, do_return, do_return, lambda: 5)
5
>>> do_return(do_return, donot_return, do_return, lambda: 5)
None

在递归函数中,这意味着每个递归路径都必须返回。


在您的情况下,到达for循环后,不会再返回任何内容。这意味着任何嵌套的递归调用都不能将值返回到调用的根。一个简单的方法是检查递归调用是否返回了有意义的值:

    ...
    found = subset_sum(remaining, target, partial + [n], result)
    if found is not None:
        return found

或者,使用例外。

但是,您的方法并非始终如一地递归 - 您result = []在每一步都修改了相同的列表。要么使用不修改其输入但返回结果的纯函数,要么直接修改并返回结果。

    ...
    subset_sum(remaining, target, partial + [n], result)
return result

一个可行的递归方法如下所示:

def subset_sum(numbers: list, target: int, split=0) -> list:
    """
    :param numbers: set of numbers to search for subsets
    :param target: the desired subset sum to search for
    :param split: index at which to split subsequences
    """
    total = sum(numbers)
    if total == target:
        return [numbers]
    elif total < target:
        return []
    else:
        results = []
        for i in range(split, len(numbers)):
            remaining = numbers[:i] + numbers[i+1:]
            results.extend(subset_sum(remaining, target, i))
        return results


if __name__ == "__main__":
    print(subset_sum([3, 9, 8, 4, 5, 7, 10], 15))
# [[5, 10], [8, 7], [3, 5, 7], [3, 8, 4]]

值得注意的是,每条路径都会返回一个有效的结果(即使它是空的)。这意味着不会丢弃任何结果。此外,返回值是将信息传递给调用者的唯一方法 - 不会修改共享数据。


推荐阅读