Python函数内省:如何获取函数中指定参数的成员引用?
实现参数成员内省的高阶函数
当然可以实现这个需求!要完成这个功能,我们需要利用Python的ast模块解析目标函数的源代码,通过遍历抽象语法树(AST),找出指定参数被访问的所有成员属性。
实现思路
- 获取函数源代码:使用
inspect模块提取目标函数的源码文本。 - 解析为AST:用
ast.parse将源码转换成抽象语法树,方便我们遍历分析。 - 遍历AST节点:递归遍历AST,找到所有
Attribute类型的节点——这类节点对应代码中的点语法访问(比如c.foo)。 - 筛选目标参数的成员:检查
Attribute节点的value部分是否是我们指定的参数名,若是则收集对应的成员名称。 - 去重并返回结果:将收集到的成员去重后以元组形式返回,没有找到则返回空元组。
完整代码实现
import ast import inspect def member_inspector(func, param_name): # 获取函数的源代码 source_code = inspect.getsource(func) # 解析为AST tree = ast.parse(source_code) # 用集合收集成员名称(自动去重) members = set() # 定义遍历AST节点的递归函数 def visit_node(node): # 匹配点语法对应的Attribute节点 if isinstance(node, ast.Attribute): # 检查是否是目标参数的成员访问 if isinstance(node.value, ast.Name) and node.value.id == param_name: members.add(node.attr) # 递归遍历所有子节点,覆盖分支、循环等所有代码块 for child in ast.iter_child_nodes(node): visit_node(child) # 开始遍历函数定义的主体部分 visit_node(tree.body[0]) # 转换为有序元组返回(sorted可选,让结果更规整) return tuple(sorted(members)) # 测试用例 def eggs(a,b,c): if c.foo: return a + b.bar else: return c.spam # 验证结果 print(member_inspector(eggs, 'c')) # 输出: ('foo', 'spam') print(member_inspector(eggs, 'b')) # 输出: ('bar',) print(member_inspector(eggs, 'a')) # 输出: ()
关键细节说明
- 去重处理:使用集合
members收集成员名称,避免同一成员被多次访问时重复返回。 - 全覆盖遍历:通过
ast.iter_child_nodes递归遍历所有子节点,确保不会漏掉if/else、循环等分支里的成员访问。 - 精准匹配:只匹配
Attribute节点的value为目标参数名的情况,避免误收集其他变量的成员。
这个实现可以处理大多数常见的函数代码结构,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Lester Jack
相关产品推荐
相关产品推荐

