如何检测Python代码中`list(np.ndarray)`的调用场景?
检测代码中
list(numpy数组)的调用 要精准识别代码里list()传入numpy数组的场景,用Python的ast库做语法分析是最优方案,以下是具体实现:
核心实现代码
import ast from typing import Set class NumpyListCallDetector(ast.NodeVisitor): def __init__(self): # 存储已识别的numpy数组变量名 self.numpy_arr_vars: Set[str] = set() # 标记是否存在目标调用 self.has_list_on_arr = False def visit_Assign(self, node: ast.Assign) -> None: # 遍历赋值语句,识别numpy数组变量 for target in node.targets: if isinstance(target, ast.Name): value = node.value # 判断赋值右侧是否是numpy的数组创建调用 if isinstance(value, ast.Call) and isinstance(value.func, ast.Attribute): # 匹配np.array、np.asarray等常见数组创建方法 if value.func.value.id == 'np' and value.func.attr in {'array', 'asarray', 'zeros', 'ones', 'arange', 'linspace'}: self.numpy_arr_vars.add(target.id) self.generic_visit(node) def visit_Call(self, node: ast.Call) -> None: # 判断是否是调用list() if isinstance(node.func, ast.Name) and node.func.id == 'list': # 检查传入的参数是否是已识别的numpy数组变量 if node.args: arg = node.args[0] if isinstance(arg, ast.Name) and arg.id in self.numpy_arr_vars: self.has_list_on_arr = True self.generic_visit(node) def is_list_on_arr(code: str) -> bool: '''检测代码中是否存在list(numpy数组)的调用''' tree = ast.parse(code) detector = NumpyListCallDetector() detector.visit(tree) return detector.has_list_on_arr if __name__ == "__main__": test_code = """ import numpy as np arr = np.array([1, 2, 3]) lst = list(arr) # 会被检测到 normal_list = list([4,5,6]) # 不会被检测到 another_arr = np.zeros(5) list(another_arr) # 会被检测到 """ print(is_list_on_arr(test_code)) # 输出: True
代码说明
- NumpyListCallDetector:继承
ast.NodeVisitor,通过遍历语法树实现两个核心逻辑:visit_Assign:识别通过np.array、np.zeros等方法创建的numpy数组变量,存入集合。visit_Call:检查所有list()调用,判断传入参数是否为已识别的numpy数组变量。
- is_list_on_arr:解析输入代码,调用检测器遍历语法树,返回检测结果。
扩展优化
如果需要覆盖更多场景,可以对检测器进行扩展:
- 处理数组别名:比如
arr_copy = arr,在visit_Assign中识别变量复制逻辑,将别名加入numpy数组变量集合。 - 处理函数返回的数组:若某函数返回numpy数组,可通过跟踪函数定义或类型注解,将接收返回值的变量标记为数组类型。
- 补充更多numpy创建方法:只需在
visit_Assign的判断列表中添加对应的方法名即可。
内容的提问来源于stack exchange,提问作者Galen
相关产品推荐
相关产品推荐

