我在第5章“标记” - 我无法解决PDF版本第186页的练习之一:
给定cfd2 ['VN']。keys()指定的过去分词列表,尝试收集紧接在该列表中项目之前的所有单词标记对的列表。 < / p>
我试过这种方式:
wsj = nltk.corpus.treebank.tagged_words(simplify_tags=True)
[wsj[wsj.index((word,tag))-1:wsj.index((word,tag))+1] for (word,tag) in wsj if word in cfd2['VN'].keys()]
但它给了我这个错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/util.py", line 401, in iterate_from
for tok in piece.iterate_from(max(0, start_tok-offset)):
File "/usr/local/lib/python2.7/dist-packages/nltk/corpus/reader/util.py", line 295, in iterate_from
self._stream.seek(filepos)
AttributeError: 'NoneType' object has no attribute 'seek'
我认为我在访问wsj结构时做错了什么,但我无法弄清楚出了什么问题!
你能帮助我吗?
提前致谢!
答案 0 :(得分:2)
wsj
的类型为nltk.corpus.reader.util.ConcatenatedCorpusView
,其行为类似于列表(这就是为什么你可以使用像index()
这样的函数),但“幕后”NLTK永远不会将整个列表读入内存,它只会从它需要的文件对象中读取这些部分。看来,如果迭代一个CorpusView对象并同时使用index()
(需要再次迭代),文件对象将返回None
。
这种方式有效,但它不如列表理解那么优雅:
for i in range(len(wsj)):
if wsj[i][0] in cfd2['VN'].keys():
print wsj[(i-1):(i+1)]
答案 1 :(得分:0)
看起来索引调用和切片都会导致异常:
wsj = nltk.corpus.treebank.tagged_words(simplify_tags=True)
cfd2 = nltk.ConditionalFreqDist((t,w) for w,t in wsj)
wanted = cfd2['VN'].keys()
# just getting the index -> exception before 60 items
for w, t in wsj:
if w in wanted:
print wsj.index((w,t))
# just slicing -> sometimes finishes, sometimes throws exception
for i, (w,t) in enumerate(wsj):
if w in wanted:
print wsj[i-1:i+1]
我猜测它是通过访问您正在迭代的流中的先前项而引起的。
如果你在wsj
上迭代一次以创建索引列表并在第二次迭代中使用它们来获取切片,它可以正常工作:
results = [
wsj[j-1:j+1]
for j in [
i for i, (w,t) in enumerate(wsj)
if w in wanted
]
]
作为旁注:在没有index
参数的情况下调用start
将每次都返回第一个匹配。
答案 2 :(得分:0)
wsj
的类型为ConcatenatedCorpusView
,我认为它在空元组('.', '.')
上窒息。最简单的解决方案是明确地将ConcatenatedCorpusView
投射到list
。你可以这样做:
wsj = list(wsj)
迭代工作正常。获取重复项的索引是一个单独的问题。请参阅:https://gist.github.com/denten/11388676