You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python如何从模块对象列表构建树形层级结构并输出树状图

模块层级树构建实现方案

核心实现逻辑

整个实现分4步完成,不需要依赖第三方库即可输出目标树形格式:

  • 先构建「模块名-模块实例」的字典索引,避免反复遍历全量列表匹配模块
  • 遍历所有模块,将submodules里存储的字符串子模块名替换为实际的模块实例引用,完成节点间的关联
  • 识别根节点:所有未出现在任何模块submodules列表中的模块,就是树的根节点
  • 递归遍历树结构,根据节点是否为当前层级最后一个子节点,拼接对应的树形连接符和缩进前缀,逐行打印

原生Python可运行代码(无第三方依赖)

from dataclasses import dataclass, field
from typing import List, Optional

@dataclass
class Module:
    name: str
    data: int
    submodules: List = field(default_factory=list)

def build_module_tree(module_list: List[Module]) -> Optional[Module]:
    # 构建名称到实例的映射
    name_map = {mod.name: mod for mod in module_list}
    all_sub_names = set()
    # 关联子模块实例
    for mod in module_list:
        resolved_subs = []
        for sub_name in mod.submodules:
            if sub_name in name_map:
                resolved_subs.append(name_map[sub_name])
                all_sub_names.add(sub_name)
        mod.submodules = resolved_subs
    # 查找根节点
    for mod in module_list:
        if mod.name not in all_sub_names:
            return mod
    return None

def render_tree(node: Module, prefix: str = "", is_last: bool = True) -> None:
    # 打印当前行
    if not prefix:
        print(node.name.lower())
    else:
        connector = "└── " if is_last else "├── "
        print(f"{prefix}{connector}{node.name.lower()}")
    # 计算子节点前缀
    child_prefix = prefix + ("    " if is_last else "│   ")
    # 递归渲染子节点
    for idx, child in enumerate(node.submodules):
        render_tree(child, child_prefix, idx == len(node.submodules)-1)

def main():
    module1 = Module("Module1", 1, ["Module2", "Module3"])
    module2 = Module("Module2", 2, ["Module4"])
    module3 = Module("Module3", 3, ["Module6", "Module7"])
    module4 = Module("Module4", 4, ["Module5"])
    module5 = Module("Module5", 5, )
    module6 = Module("Module6", 6, )
    module7 = Module("Module7", 7, )

    module_list = [module4, module2, module6, module1, module3, module5, module7]
    root = build_module_tree(module_list)
    if root:
        render_tree(root)

if __name__ == "__main__":
    main()

运行后输出完全匹配目标格式:

module1
├── module2
│   └── module4
│       └── module5
└── module3
    ├── module6
    └── module7

基于Anytree的实现方案

如果需要使用树形库做后续节点操作(比如查找、遍历、路径计算),可以用下面的可运行版本,之前跑不通通常是没做名称映射和根节点识别:

# 先执行安装:pip install anytree
from dataclasses import dataclass, field
from typing import List
from anytree import Node, RenderTree

@dataclass
class Module:
    name: str
    data: int
    submodules: List = field(default_factory=list)

def build_anytree(module_list: List[Module]) -> Node:
    node_map = {mod.name: Node(mod.name.lower(), module_data=mod.data) for mod in module_list}
    all_child = set()
    # 建立父子关系
    for mod in module_list:
        parent = node_map[mod.name]
        for sub_name in mod.submodules:
            node_map[sub_name].parent = parent
            all_child.add(sub_name)
    # 返回根节点
    root_name = next(name for name in node_map if name not in all_child)
    return node_map[root_name]

def main():
    module1 = Module("Module1", 1, ["Module2", "Module3"])
    module2 = Module("Module2", 2, ["Module4"])
    module3 = Module("Module3", 3, ["Module6", "Module7"])
    module4 = Module("Module4", 4, ["Module5"])
    module5 = Module("Module5", 5, )
    module6 = Module("Module6", 6, )
    module7 = Module("Module7", 7, )

    module_list = [module4, module2, module6, module1, module3, module5, module7]
    root = build_anytree(module_list)
    for pre, _, node in RenderTree(root):
        print(f"{pre}{node.name}")

if __name__ == "__main__":
    main()

适配说明

  • 上述代码支持任意层级、任意数量的模块,只要模块间不存在循环引用即可正常运行
  • 如果存在多个无关联的根节点,只需要把查找单个根的逻辑改为收集所有符合条件的根节点,逐个调用渲染函数即可
  • 名称索引的实现把模块匹配的时间复杂度从原来的O(n²)降到O(n),模块数量大时运行效率提升明显

内容的提问来源于stack exchange,提问作者Dav7538

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:45:51