Python嵌套类:如何从Fitter访问外部Tokenizer父类对象?
问题描述
现有嵌套类结构(需保留此结构),需要通过内部Fitter类修改外部Tokenizer类的vocabulary属性,但不清楚如何访问Tokenizer的实例对象。
类定义代码:
class Tokenizer(TokenizerABC): def __init__( self, vocabulary, pre_tokenizer ): self._vocabulary = vocabulary self._pre_tokenizer = pre_tokenizer class Fitter(TokenizerABC.Fitter["Tokenizer"]): """一种构建器风格的对象,用于将分词器适配到语料库。""" def __init__(self, lowercase=False, limit=None): ... def fit(self, corpus: list[str]) -> TokenizerABC: """将分词器适配到给定语料库。 参数: corpus (list[str]): 要适配的语料库。 返回: Parent (Generic[TokenizerABC]): 适配后的分词器。 """ # 一些代码 vocabulary = # 一些代码 return ... @classmethod def fitter(cls) -> Fitter["Tokenizer"]: """为此分词器创建一个新的Fitter对象。 返回: Fitter[Self]: 此分词器的Fitter对象。 """ return ...
测试代码调用方式:
abcd = ["a a a b", "c c c d d"] tokenizer = Tokenizer.fitter().fit(abcd)
使用Python版本:3.12
解决方案
结合你的代码结构和调用逻辑,提供两种适配场景的实现方案:
1. 生成新的Tokenizer实例(契合现有测试代码逻辑)
这是最贴合当前调用方式的方案:在fit方法中生成适配后的词汇表,直接实例化Tokenizer并返回,自然完成vocabulary的赋值。
修改后代码:
class Tokenizer(TokenizerABC): def __init__( self, vocabulary, pre_tokenizer ): self._vocabulary = vocabulary self._pre_tokenizer = pre_tokenizer class Fitter(TokenizerABC.Fitter["Tokenizer"]): """一种构建器风格的对象,用于将分词器适配到语料库。""" def __init__(self, lowercase=False, limit=None): self.lowercase = lowercase self.limit = limit # 初始化预分词器(根据实际逻辑调整) self._pre_tokenizer = None def fit(self, corpus: list[str]) -> "Tokenizer": """将分词器适配到给定语料库。""" # 模拟生成词汇表的业务逻辑 vocabulary = {} for text in corpus: tokens = text.split() if self.lowercase: tokens = [t.lower() for t in tokens] for token in tokens: vocabulary[token] = vocabulary.get(token, 0) + 1 # 按limit截取高频词汇(如果设置了limit) if self.limit: vocabulary = dict(sorted(vocabulary.items(), key=lambda x: x[1], reverse=True)[:self.limit]) # 实例化外部Tokenizer类,传入生成的词汇表 return Tokenizer(vocabulary=vocabulary, pre_tokenizer=self._pre_tokenizer) @classmethod def fitter(cls) -> Fitter["Tokenizer"]: """为此分词器创建一个新的Fitter对象。""" return cls.Fitter()
2. 修改已存在的Tokenizer实例
如果需求是修改已创建的Tokenizer实例的vocabulary,可以让Fitter初始化时持有外部实例的引用,再在fit方法中直接修改属性:
修改后代码:
class Tokenizer(TokenizerABC): def __init__( self, vocabulary=None, pre_tokenizer=None ): self._vocabulary = vocabulary or {} self._pre_tokenizer = pre_tokenizer class Fitter(TokenizerABC.Fitter["Tokenizer"]): """一种构建器风格的对象,用于将分词器适配到语料库。""" def __init__(self, tokenizer: "Tokenizer", lowercase=False, limit=None): self.tokenizer = tokenizer # 持有外部Tokenizer实例引用 self.lowercase = lowercase self.limit = limit def fit(self, corpus: list[str]) -> "Tokenizer": """将分词器适配到给定语料库,并修改原有实例的vocabulary""" # 模拟生成词汇表的业务逻辑 vocabulary = {} for text in corpus: tokens = text.split() if self.lowercase: tokens = [t.lower() for t in tokens] for token in tokens: vocabulary[token] = vocabulary.get(token, 0) + 1 if self.limit: vocabulary = dict(sorted(vocabulary.items(), key=lambda x: x[1], reverse=True)[:self.limit]) # 直接修改已有实例的_vocabulary属性 self.tokenizer._vocabulary = vocabulary return self.tokenizer @classmethod def fitter(cls, tokenizer=None) -> Fitter["Tokenizer"]: """为此分词器创建一个新的Fitter对象。""" if tokenizer is None: tokenizer = cls() return cls.Fitter(tokenizer)
对应调用方式:
abcd = ["a a a b", "c c c d d"] # 方式1:生成新实例 tokenizer = Tokenizer.fitter().fit(abcd) # 方式2:修改已有实例 existing_tokenizer = Tokenizer() Tokenizer.fitter(existing_tokenizer).fit(abcd)
关键说明
- Python嵌套类可以直接访问外部类的名称,但要访问外部类的实例,必须显式持有引用。
- 第一种方案完全匹配你提供的测试代码调用逻辑,是更推荐的实现方式。
- Python 3.12的泛型注解支持完善,你使用的
Fitter["Tokenizer"]写法符合语法规范。
内容的提问来源于stack exchange,提问作者Herakles
相关产品推荐
相关产品推荐

