You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 09:23:12