如何用Python AST提取类、类内函数及函数调用?求示例代码
用AST提取Python代码中的类、方法及内部函数调用示例
我明白你想用AST提取Python代码里的类、类中的方法,还有每个方法内部调用的函数——之前的代码只遍历了所有ast.Name节点,确实没法精准区分这些元素。下面是一个能满足你需求的完整示例代码,还会附带详细的解释:
完整示例代码
import ast from typing import Dict, List def analyze_python_code(file_path: str) -> Dict[str, Dict[str, List[str]]]: """ 分析Python文件,提取类、类中的方法,以及每个方法内部调用的函数 返回结构: {类名: {方法名: [调用的函数列表]}} """ with open(file_path, 'r', encoding='utf-8') as f: code = f.read() tree = ast.parse(code, filename=file_path) result = {} # 遍历所有类节点 for node in ast.walk(tree): if isinstance(node, ast.ClassDef): class_name = node.name result[class_name] = {} # 遍历类下的所有方法/函数 for item in node.body: if isinstance(item, ast.FunctionDef): func_name = item.name called_funcs = [] # 遍历函数内部的所有调用节点 for sub_node in ast.walk(item): if isinstance(sub_node, ast.Call): # 处理直接调用的函数(比如 func()) if isinstance(sub_node.func, ast.Name): called_funcs.append(sub_node.func.id) # 处理属性调用(比如 obj.method()) elif isinstance(sub_node.func, ast.Attribute): called_funcs.append(f"{sub_node.func.value.id}.{sub_node.func.attr}") result[class_name][func_name] = called_funcs return result # 使用示例 if __name__ == "__main__": analysis_result = analyze_python_code("test.py") for class_name, methods in analysis_result.items(): print(f"* 类: {class_name}") for method_name, called_funcs in methods.items(): print(f" - 方法: {method_name}") if called_funcs: print(f" 调用的函数: {', '.join(called_funcs)}") else: print(f" 未调用任何函数")
代码关键逻辑说明
- 文件解析与AST生成:用
with语句安全读取文件,避免资源泄漏;通过ast.parse()将代码字符串转换为AST语法树,指定filename参数能让报错信息更准确。 - 提取类节点:筛选
ast.ClassDef类型的节点,获取类的名称(node.name)。 - 提取类中的方法:在类节点的
body属性中,筛选ast.FunctionDef节点,这些就是类的方法(包括普通方法、类方法、静态方法,如需区分可进一步判断decorator_list属性)。 - 提取方法内部的函数调用:在方法节点内部遍历
ast.Call节点,区分两种常见调用场景:- 直接调用普通函数(如
print()):对应ast.Name类型的func属性,提取id即为函数名。 - 属性调用(如
self.get_data()、requests.get()):对应ast.Attribute类型的func属性,拼接value.id(对象/模块名)和attr(方法名)得到完整调用路径。
- 直接调用普通函数(如
- 返回结构化结果:用嵌套字典存储数据,方便后续的遍历、输出或进一步处理。
小技巧:探索AST节点结构
如果觉得官方文档不够清晰,你可以在遍历节点时打印节点的属性字典,快速了解节点包含的信息:
for node in ast.walk(tree): if isinstance(node, ast.Call): print(vars(node)) # 打印节点的所有属性和值
内容的提问来源于stack exchange,提问作者Coder




