如何从Python习题集提取内置函数、过滤自定义函数并统计频次
实现方案
核心问题解决思路
- 自定义函数过滤:先提取每道题中所有
def关键字定义的函数名,存入自定义函数黑名单,后续匹配到的函数名如果在黑名单中直接丢弃;内置函数直接以Python标准库builtins模块中的内置函数列表作为白名单,无需手动枚举。 - 正则匹配规则:用零宽断言区分普通内置函数调用和方法调用,避免误匹配:
- 方法调用匹配:匹配点号
.后直接跟随的、带括号的标识符,仅捕获点号后的方法名部分,例如从list.append('a')中仅捕获append - 普通函数调用匹配:匹配前面为行首、空白符、运算符/括号/逗号等非标识符字符的、带括号的标识符,不会把
list.append这类链式调用的前缀对象名误判为函数
- 方法调用匹配:匹配点号
完整实现代码
import re import builtins import collections # step1: 生成内置函数白名单:筛选builtins中所有可调用的内置函数 # 如果需要把int()/str()/list()这类内置类型构造函数也算入,移除下面的not isinstance(obj, type)判断即可 builtin_funcs = set() for name in dir(builtins): obj = getattr(builtins, name) if callable(obj) and not isinstance(obj, type): builtin_funcs.add(name) # 内置方法集合,可根据数据集实际出现的方法动态补充 builtin_methods = { 'append', 'pop', 'insert', 'remove', 'sort', 'reverse', 'index', 'count', # list方法 'split', 'join', 'strip', 'replace', 'find', 'upper', 'lower', 'startswith', 'endswith', 'format', # str方法 'keys', 'values', 'items', 'get', 'update', 'pop' # dict方法 } builtin_all = builtin_funcs | builtin_methods # 匹配def定义的自定义函数的正则 re_define = re.compile(r'def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(') # 匹配函数/方法调用的正则:两个捕获组,第一个是点后的方法名,第二个是普通函数名 re_call = re.compile(r''' (?<=\.)([a-zA-Z_][a-zA-Z0-9_]*)\s*\( # 匹配方法调用,捕获点后的方法名 | (?<![a-zA-Z0-9_.])([a-zA-Z_][a-zA-Z0-9_]*)\s*\( # 匹配普通函数调用,捕获函数名 ''', re.VERBOSE) def extract_funcs_from_question(question_text: str) -> list: # 提取当前题目所有自定义函数名加入黑名单 custom_funcs = set(re_define.findall(question_text)) matched = [] for match in re_call.finditer(question_text): method_name, func_name = match.groups() target = method_name if method_name else func_name # 过滤自定义函数,只保留在内置白名单里的项 if target not in custom_funcs and target in builtin_all: matched.append(f"{target}()") return matched # 测试官方样例 sample_question = """ 以下Python代码的运行输出结果是什么? x = 50 def func(): global x print('x is', x) x = 2 print('Changed global x to', x) func() print('Value of x is', x) """ print(extract_funcs_from_question(sample_question)) # 输出 ['print()', 'print()', 'print()'],自定义函数func()被正确过滤,符合预期 if __name__ == "__main__": # 替换为实际全量数据集,每个元素为单道题的完整字符串 all_questions = [sample_question] all_func_set = set() question_func_list = [] # 遍历所有题目提取函数,汇总不重复的统一函数列表 for q in all_questions: funcs = extract_funcs_from_question(q) question_func_list.append(funcs) all_func_set.update(funcs) unified_func_list = sorted(list(all_func_set)) # 统计每道题的函数出现频次 for idx, funcs in enumerate(question_func_list): count_res = collections.Counter(funcs) print(f"第{idx+1}题函数频次统计:{dict(count_res)}")
可选优化点
- 如果需要排除字符串、注释中出现的误匹配,可以在匹配前先预处理文本,用正则移除所有引号包裹的字符串内容、
#开头的注释行 - 如果题目中存在自定义类定义,可以补充正则匹配
class关键字定义的类名,同时过滤自定义类实例的方法调用 - 内置方法集合可以通过遍历Python内置类型的公开方法自动生成,无需手动维护
内容的提问来源于stack exchange,提问作者Harikesh Pratap Singh
相关产品推荐
相关产品推荐

