Skip to main content
 首页 » 编程设计

Python: "pass by reference"在递归提取中是否可以接受

2025年05月04日14jyk

我必须从树结构中提取节点,以便获得树中所有节点的平面列表。我想到了两个方案

干净、可读但可能效率不高,因为有很多列表合并:

def _recursive_extraction(node): 
    store = [] 
 
    # .get_subnodes() returns only the direct children 
    for subnode in node.get_subnodes(): 
        store.append(subnode) 
 
        subsubnodes = _recursive_extraction(subnode) 
        store += subsubnodes 
 
    return store 

而且(可能)效率更高,但可读性较差。我的老板试图说服我使用它,但我怀疑。它在一个可变对象内部传递,该对象被隐式/隐藏地更新,在其他语言中称为“按引用传递”。

def _recursive_extraction(node, store=None): 
    if store is None: 
        store = [] 
 
    for subnode in node.get_subnodes(): 
        store.append(subnode) 
 
        # Watch out! store is updated in this func call 
        _recursive_extraction(subnode, store)         
 
    return store 

免责声明:代码未经测试,仅表达我的想法。

免责声明 2:“通过引用”是指传递可以更新的可变对象。

边编辑:将子节点批量附加到循环之外会更有效,像这样:

def _recursive_extraction(node, store=None): 
    if store is None: 
        store = [] 
 
    subnodes = node.get_subnodes() 
    store += subnodes 
 
    for subnode in subnodes: 
 
        # Watch out! store is updated in this func call 
        _recursive_extraction(subnode, store)         
 
    return store 

请您参考如下方法:

可能有点跑题,但是你考虑过使用生成器吗?

尽可能明确。您指定它应该产生给定的节点值,以及从该节点提取的所有节点:

def _recursive_extraction(node): 
    for subnode in node.get_subnodes(): 
        yield subnode 
 
        yield from _recursive_extraction(subnode) 

此外,指定提取算法的优点是无需指定提取数据的容器。

最后但同样重要的是,它可能比第一个解决方案更快/内存效率更高——如果你想在提取的节点上迭代一次,那么这就是你需要的,如果你想存储它,传递这个生成器到 list()。如果构造函数比扩展列表更快(我认为它可能是),那么您就可以加速,并且不需要中间数据结构。