Python初学者疑问:类属性与实例属性该如何选择?
问题分析与解决方案
首先明确:必须把sentences和tokens改成实例属性,类属性是所有实例共享的,如果你创建多个Text实例,类属性会被不同实例的数据覆盖,导致逻辑混乱。每个Text实例应该独立处理自己的输入文本,所以这些属性必须绑定到实例(用self.前缀)。
你的原代码存在几个明显问题:
- 类属性定义阶段调用
sent_tokenize(text),此时text还未被传入(__init__才是接收输入文本的地方),会直接抛出NameError; tokens.append()没有传入参数,属于语法错误;- 直接对整个文本调用
word_tokenize(text),无法区分句子结构,满足不了“识别token是否位于句首”的要求。
修正后的代码
首先确保导入并下载NLTK必要的分词模型:
import nltk nltk.download('punkt') from nltk.tokenize import sent_tokenize, word_tokenize
然后编写正确的Text类:
class Text: def __init__(self, text): self.raw_text = text # 拆分原始文本为句子列表,保存为实例属性 self.sentences = sent_tokenize(text) # 对每个句子单独分词,生成二维tokens列表(每个子列表对应一个句子的token) self.tokens = [word_tokenize(sentence) for sentence in self.sentences] # 可选:添加方法判断某个token是否为对应句子的句首 def is_sentence_start(self, token_pos, sentence_pos): # 先检查索引合法性 if sentence_pos < 0 or sentence_pos >= len(self.tokens): return False target_sentence = self.tokens[sentence_pos] if token_pos < 0 or token_pos >= len(target_sentence): return False # 句首token的索引为0 return token_pos == 0
关键说明
- 实例属性的必要性:
self.sentences和self.tokens属于每个Text实例,不同实例处理不同文本时不会互相干扰; - 二维tokens结构:
self.tokens是一个二维列表,比如[["Hello", "world", "!"], ["This", "is", "a", "test", "."]],每个子列表对应一个句子的分词结果,天然能体现句子结构——子列表的第一个元素就是句首token; - 分词逻辑修正:先拆分句子,再对每个句子单独分词,确保token和句子的对应关系。
使用示例
# 创建实例 test_text = "Hi there! I'm a Python beginner. Thanks for your help." text_instance = Text(test_text) # 查看拆分后的句子 print("拆分后的句子:", text_instance.sentences) # 查看带句子结构的tokens print("Tokens列表:", text_instance.tokens) # 判断是否为句首 print("是否是句首:", text_instance.is_sentence_start(0, 1)) # True,第二个句子的第一个token print("是否是句首:", text_instance.is_sentence_start(2, 1)) # False,第二个句子的第三个token
内容的提问来源于stack exchange,提问作者beginner_programmer
相关产品推荐
相关产品推荐

