想要一些帮助使函数尾递归

Wanted some help making a function tail recursive

我在 python 中创建了一个函数来展平字典对象。此类对象的示例如下:

x = {'items': [{'name': 'Contract',
     'subItems': [{'name': 'Consultant'}, {'name': 'Direct'}]},
       {'name': 'Permanent',
        'subItems': [{'name': 'Full Time'}, {'name': 'Part Time'}]}]}

我现在使用的函数使用了一个单独的列表。这是函数:

final_list = []
def traverseGraph(g_list, level=[]):
        for g_ in g_list:
            if 'subItems' in g_:
                traverseGraph(g_['subItems'], level+[g_['name']])
            else:
                final_list.append(level+[g_['name']])

给出以下正确输出:

traverseGraph(x['items'])

final_list
[['Contract', 'Consultant'],
 ['Contract', 'Direct'],
 ['Permanent', 'Full Time'],
 ['Permanent', 'Part Time']]

我想将此函数转换为不使用单独列表的尾递归函数。这是我有的,但不起作用。

def traverseGraph(g_list, level=[]):
        for g_ in g_list:
            if 'subItems' not in g_:
                return (level + [g_['name']])
            return traverseGraph(g_['subItems'], level + [g_['name']])

这是输出:

a = traverseGraph(x['items'])
print(a)
['Contract', 'Consultant']

我可以使用该列表,但我不想使用。在这一点上,它只是为了学习。谢谢!

这似乎可以很好地用作递归生成器:

def traverseGraph(g_list, level=[]):
    for g_ in g_list:
        if 'subItems' in g_:
            yield from traverseGraph(g_['subItems'], level+[g_['name']])
        else:
            yield level+[g_['name']]

如果您真的想坚持使用列表但想要 return 您的结果,您要么需要将结果列表传递到调用链中,要么需要合并递归结果进入每个级别的列表。下面是将结果列表传递到调用链中的样子:

def traverseGraph(g_list, level=[], final_list=None):
    if final_list is None:
        final_list = []
    for g_ in g_list:
        if 'subItems' in g_:
            traverseGraph(g_['subItems'], level+[g_['name']], final_list)
        else:
            final_list.append(level+[g_['name']])
    return final_list

这是合并的样子:

def traverseGraph(g_list, level=[]):
    final_list = []
    for g_ in g_list:
        if 'subItems' in g_:
            final_list.extend(traverseGraph(g_['subItems'], level+[g_['name']]))
        else:
            final_list.append(level+[g_['name']])
    return final_List

合并版本需要更多的数据复制,因此效率会降低。

None 这些实现是尾递归的。您可能需要多次递归,所以这不是一个真正的选择。