如何重写TfidfVectorizer的build_preprocessor实现预处理链式调用
实现方案
你不需要改动父类方法的原有分支逻辑,只要在自定义的嵌套预处理器函数中,先调用父类返回的预处理器处理原始文档,再把输出结果传入你的自定义逻辑做二次处理即可,调用链会自动按「父类预处理 -> 自定义追加预处理」的顺序执行。
需要修正的原有代码问题
- 原
__init__方法没有透传父类的初始化参数,会导致TfidfVectorizer原生支持的所有配置(比如ngram_range、max_features等)全部失效 - 直接用
open读文件没有关闭句柄,会造成资源泄漏 - 用
readlines读取的后缀列表每行末尾会带换行符,后续匹配逻辑容易出异常
修正后可直接运行的代码
from functools import partial from sklearn.feature_extraction.text import TfidfVectorizer class MyTfidfVectorizer(TfidfVectorizer): def __init__(self, some_file, **kwargs): # 透传所有父类支持的初始化参数,保留原生组件的全部配置能力 super().__init__(**kwargs) # 用上下文管理器自动关闭文件,同时清理每行的换行、空白字符 with open(some_file, 'r', encoding='utf-8') as f: self.suffixes = [line.strip() for line in f if line.strip()] def build_preprocessor(self): # 拿到父类根据当前参数生成的预处理器,自动兼容其内部所有分支判断 parent_preprocessor = super().build_preprocessor() def custom_preprocessor(doc, suffixes, threshold=2): # 第一步:执行父类预置的全部预处理逻辑 doc_processed = parent_preprocessor(doc) # 第二步:在此处编写你的自定义追加预处理逻辑,操作doc_processed即可 # 以下为示例逻辑,替换成你自己的业务实现即可 for suf in suffixes: if doc_processed.endswith(suf) and len(suf) >= threshold: doc_processed = doc_processed[:-len(suf)].strip() return doc_processed # 绑定固定参数后返回符合父类调用规范的预处理器函数 return partial(custom_preprocessor, suffixes=self.suffixes)
逻辑说明
- 父类的
build_preprocessor会根据初始化时传入的参数(比如是否转小写、是否做文本清洗、是否传入了用户自定义预处理器等)自动返回对应处理逻辑的函数,你不需要关心其内部分支,直接调用返回值即可 - 你封装后返回的自定义预处理器,会被TfidfVectorizer后续的分词、词频统计流程自动调用,执行顺序完全符合预期
- 如果需要调整自定义逻辑的参数(比如示例里的
threshold),可以把它加到__init__的参数列表中,绑定为实例属性后再通过partial传入即可
内容的提问来源于stack exchange,提问作者Sarvo
相关产品推荐
相关产品推荐

