Python SpaCy:文档被删除后如何继续存在和工作?

Python SpaCy:文档被删除后如何继续存在和工作?,python,spacy,Python,Spacy,从: 文档是一系列令牌对象。访问句子并命名 实体,将注释导出到numpy数组,无损序列化到 压缩的二进制字符串。Doc对象包含一个TokenC数组 结构。Python级别的标记和Span对象是此对象的视图 数组,即他们自己不拥有数据 这有点道理,但我很想知道它到底是如何工作的,特别是因为,正如我在下面所展示的,可以删除Doc对象(或者至少是指向它的变量),并且它会继续工作 import spacy nlp = spacy.load('en_core_web_sm') from sys impor

从:

文档是一系列令牌对象。访问句子并命名 实体,将注释导出到numpy数组,无损序列化到 压缩的二进制字符串。Doc对象包含一个TokenC数组 结构。Python级别的标记和Span对象是此对象的视图 数组,即他们自己不拥有数据

这有点道理,但我很想知道它到底是如何工作的,特别是因为,正如我在下面所展示的,可以删除
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
    及其标记之间创建一个引用循环,从而打乱引用计数。有很多方法可以解决这个问题(使用弱引用),但最终净成本使其变得不值得——最好只做简单的事情,每次创建一个新的
    标记
    对象。这也有助于人们编写几乎可以工作的代码——几乎正确的代码通常是最糟糕的错误类型