Python递归函数实现嵌套YAML字段的点分隔路径列表生成
递归遍历嵌套YAML生成叶子节点点分隔路径的Python实现
问题场景
给定多层嵌套的YAML数据,需要生成所有叶子字段的完整路径(用点分隔层级),而非中间父节点的路径。
输入示例
person: name: Alice contact: email: alice@example.com phone: home: 123456 work: 789012 address: street: Main St zip: 10001
现有代码及问题
现有递归函数会把中间层级路径也加入结果:
def get_paths(obj, parent=""): paths = [] if isinstance(obj, dict): for key, value in obj.items(): new_parent = f"{parent}.{key}" if parent else key paths.append(new_parent) paths.extend(get_paths(value, new_parent)) return paths
当前输出(不符合预期)
['person', 'person.name', 'person.contact', 'person.contact.email', 'person.contact.phone', 'person.contact.phone.home', 'person.contact.phone.work', 'address', 'address.street', 'address.zip']
期望输出
['person.name', 'person.contact.email', 'person.contact.phone.home', 'person.contact.phone.work', 'address.street', 'address.zip']
问题根源
现有代码在遍历字典时,直接将当前层级的路径(如person、person.contact)加入结果,而我们只需要最终叶子节点的路径。
正确实现
修改递归逻辑,仅当遍历到非容器类型的叶子节点时,才将路径加入结果;若为嵌套字典或列表,则继续递归处理:
def get_paths(obj, parent=""): paths = [] if isinstance(obj, dict): for key, value in obj.items(): current_path = f"{parent}.{key}" if parent else key # 递归处理子节点,收集子节点的路径 child_paths = get_paths(value, current_path) paths.extend(child_paths) elif isinstance(obj, list): # 处理列表类型,用索引作为路径的一部分 for idx, item in enumerate(obj): current_path = f"{parent}.{idx}" if parent else str(idx) paths.extend(get_paths(item, current_path)) else: # 非容器类型,添加当前完整路径 paths.append(parent) return paths
测试验证
加载YAML数据并调用函数,即可得到预期结果:
import yaml # 加载示例YAML yaml_content = """ person: name: Alice contact: email: alice@example.com phone: home: 123456 work: 789012 address: street: Main St zip: 10001 """ data = yaml.safe_load(yaml_content) print(get_paths(data)) # 输出:['person.name', 'person.contact.email', 'person.contact.phone.home', 'person.contact.phone.work', 'address.street', 'address.zip']
扩展说明
- 上述实现支持处理列表嵌套,比如YAML包含数组时,会生成带索引的路径(如
person.hobbies.0) - 如果需要保留中间层级路径,只需调整逻辑,在遍历字典时先将
current_path加入paths再递归即可
内容的提问来源于stack exchange,提问作者ap3x
相关产品推荐
相关产品推荐

