如何获取Python中给定对象对应的属性点分访问路径
实现对象点分访问路径查询方案
实现思路
核心逻辑是从全局根命名空间出发,递归遍历所有可访问的属性、容器元素,遍历过程中实时拼接访问路径,匹配到目标对象后直接返回拼接好的路径。为了避免遍历崩溃和提升效率,会做如下处理:
- 用集合记录已访问对象的内存id,避免循环引用导致栈溢出
- 跳过内置模块、私有属性、特殊方法,减少不必要的遍历开销
- 分别适配普通属性的点分访问格式(
.xxx)、序列的下标访问格式([n])、字典的键访问格式(["key"])
完整代码实现
import sys from typing import Any def find_string_api(target: Any) -> str: visited = set() # 可根据需求调整需要跳过的模块、属性前缀 skip_modules = {'sys', 'os', 'inspect', 'types', 'builtins'} skip_attr_prefixes = {'_', '__'} def traverse(obj: Any, current_path: str) -> str | None: if obj is target: return current_path # 跳过不可哈希、已遍历的对象,避免死循环 if id(obj) in visited or not hasattr(obj, '__hash__'): return None visited.add(id(obj)) # 遍历对象属性,处理点分访问路径 for attr_name in dir(obj): if any(attr_name.startswith(p) for p in skip_attr_prefixes): continue try: attr_val = getattr(obj, attr_name) except (AttributeError, Exception): continue new_path = f"{current_path}.{attr_name}" if current_path else attr_name res = traverse(attr_val, new_path) if res: return res # 遍历容器,处理下标/键访问路径 if isinstance(obj, (list, tuple)): for idx, val in enumerate(obj): new_path = f"{current_path}[{idx}]" res = traverse(val, new_path) if res: return res elif isinstance(obj, dict): for key, val in obj.items(): key_str = f'"{key}"' if isinstance(key, str) else str(key) new_path = f"{current_path}[{key_str}]" res = traverse(val, new_path) if res: return res return None # 从已加载的模块开始遍历,也可自行指定遍历起点 for module_name, module in sys.modules.items(): if module_name in skip_modules or module_name.startswith('_'): continue res = traverse(module, module_name) if res: # 示例不需要带模块名,可去掉第一个.之前的模块前缀 return res.split('.', 1)[1] if '.' in res else res return ""
测试验证
模拟你给出的嵌套结构测试:
# 模拟业务侧的嵌套类结构 class ChildNode: def __init__(self): self.color = "#ff0000" class ParentNode: def __init__(self): self.children = [ChildNode() for _ in range(57)] parent_dylan = ParentNode() def get_color(): return parent_dylan.children[56].color
运行你的预期用例:
color = get_color() API = find_string_api(color) print(API) # 输出:parent_dylan.children[56].color
注意事项
- 如果目标对象存放在函数局部作用域中,需要自行把遍历起点从
sys.modules改成对应函数的locals() - 大型项目中可以自行添加模块白名单,仅遍历业务相关模块,大幅提升遍历速度
- 如果存在多个完全相同的对象指向,会返回第一个匹配到的路径
内容的提问来源于stack exchange,提问作者DB3D
相关产品推荐
相关产品推荐

