Python SpaCy:文档被删除后如何继续存在和工作?
从: 文档是一系列令牌对象。访问句子并命名 实体,将注释导出到numpy数组,无损序列化到 压缩的二进制字符串。Doc对象包含一个TokenC数组 结构。Python级别的标记和Span对象是此对象的视图 数组,即他们自己不拥有数据 这有点道理,但我很想知道它到底是如何工作的,特别是因为,正如我在下面所展示的,可以删除Python SpaCy:文档被删除后如何继续存在和工作?,python,spacy,Python,Spacy,从: 文档是一系列令牌对象。访问句子并命名 实体,将注释导出到numpy数组,无损序列化到 压缩的二进制字符串。Doc对象包含一个TokenC数组 结构。Python级别的标记和Span对象是此对象的视图 数组,即他们自己不拥有数据 这有点道理,但我很想知道它到底是如何工作的,特别是因为,正如我在下面所展示的,可以删除Doc对象(或者至少是指向它的变量),并且它会继续工作 import spacy nlp = spacy.load('en_core_web_sm') from sys impor
Doc
对象(或者至少是指向它的变量),并且它会继续工作
import spacy
nlp = spacy.load('en_core_web_sm')
from sys import getsizeof
doc = nlp('King Henry VIII married six times.')
print(doc)
print(getsizeof(doc))
token = doc[0]
print(token)
print(getsizeof(token))
span = doc[:3]
del doc
span.merge() # This updates the vestigial doc despite deletion.
print(token)
print(getsizeof(token)) # Same size as before, being just a pointer.
print(token.doc) # Doc can be retrieved.
print(getsizeof(token.doc))
输出:
King Henry VIII married six times.
184
King
80
King Henry VIII
80
King Henry VIII married six times.
184
鉴于我对Python的基本知识,我很想知道:
Doc
对象存储在内存中的确切位置和方式,以允许上述操作token
变量可以调用此对象,其所有功能为80字节,为什么doc
变量的大小应该是184字节的两倍以上那么,您可以在这里找到代码:。它在Cython中,因此有一些额外的概念,但您可能仍然会发现它很有用 简单的回答是,
Span
和Token
对象确实持有对Doc
的引用,即使在删除Doc
变量后,该引用仍保持Doc
对象的活动状态。这允许您继续查询文档
但是,doc
没有任何对其Span
或标记
对象的引用。这些对象完全是暂时的:每次编写doc[i]
时,都会重新创建一个新的Token
实例。请查看doc.pyx
中的\uuu getitem\uuuuuuu
实现,以了解这种情况
spaCy的早期版本确实缓存了
令牌
对象,希望提高某些访问模式的效率。但是,这会在doc
及其标记之间创建一个引用循环,从而打乱引用计数。有很多方法可以解决这个问题(使用弱引用),但最终净成本使其变得不值得——最好只做简单的事情,每次创建一个新的标记对象。这也有助于人们编写几乎有效的代码——几乎正确的代码通常是最糟糕的错误类型。好的,您可以在这里找到代码:。它在Cython中,因此有一些额外的概念,但您可能仍然会发现它很有用
简单的回答是,Span
和Token
对象确实持有对Doc
的引用,即使在删除Doc
变量后,该引用仍保持Doc
对象的活动状态。这允许您继续查询文档
但是,doc
没有任何对其Span
或标记
对象的引用。这些对象完全是暂时的:每次编写doc[i]
时,都会重新创建一个新的Token
实例。请查看doc.pyx
中的\uuu getitem\uuuuuuu
实现,以了解这种情况
spaCy的早期版本确实缓存了令牌
对象,希望提高某些访问模式的效率。但是,这会在doc
及其标记之间创建一个引用循环,从而打乱引用计数。有很多方法可以解决这个问题(使用弱引用),但最终净成本使其变得不值得——最好只做简单的事情,每次创建一个新的标记对象。这也有助于人们编写几乎可以工作的代码——几乎正确的代码通常是最糟糕的错误类型