我知道在这个问题上有几个非常相似的答案,但是没有一个真正回答我的问题。
我正试图从一个单词列表中删除一系列停用词和标点符号来执行基本的自然语言处理。
from nltk.tokenize import word_tokenize, sent_tokenize
from nltk.corpus import stopwords
from string import punctuation
text = "Hello there. I am currently typing Python. "
custom_stopwords = set(stopwords.words('english')+list(punctuation))
# tokenizes the text into a sentence
sentences = sent_tokenize(text)
# tokenizes each sentence into a list of words
words = [word_tokenize(sentence) for sentence in sentences]
filtered_words = [word for word in words if word not in custom_stopwords]
print(filtered_words)
这会在TypeError: unhashable type: 'list'
线上引发filtered_words
错误。为什么抛出这个错误?我根本不提供list
系列 - 我提供set
?
注意:我已经阅读了关于SO on this exact error的帖子,但仍然有同样的问题。接受的答案提供了这样的解释:
套装要求其物品可以清洗。在Python预定义的类型中,只有不可变的类型(如字符串,数字和元组)是可清除的。可变类型(例如列表和dicts)不可清除,因为更改其内容会更改哈希并中断查找代码。
我在这里提供了一组字符串,为什么Python仍然在抱怨?
编辑:在阅读更多这个SO post,建议使用tuples
后,我编辑了我的集合对象:
custom_stopwords = tuple(stopwords.words('english'))
我还意识到我必须压扁我的列表,因为word_tokenize(sentence)
将创建一个列表列表,并且不会正确过滤掉标点符号(因为列表对象不会在custom_stopwords
中,这是一个字符串列表。
然而,这仍然引出了一个问题 - 为什么元组被认为是可以通过Python进行的,但字符串集不是?为什么TypeError
说list
?
words
是列表,因为word_tokenize()
返回一个单词列表。
当你做[word for word in words if word not in custom_stopwords]
每个word
实际上是list
类型。当需要检查word not in custom_stopwords
“处于设置”状态时,需要对word
进行哈希处理,因为列表是可变容器并且在Python中不可清除。
这些帖子可能有助于理解什么是“hashable”以及为什么可变容器不是: