64

我遇到了这个关于字典内存管理的问题,其中提到了实习生功能。它到底是做什么的,什么时候使用?

举个例子:如果我有一个名为seen的集合,它包含格式为 (string1,string2) 的元组,我用它来检查重复项,存储 (intern(string1),intern(string2)) 会提高内存性能还是速度?

4

4 回答 4

84

Python 3文档

sys.intern(string)

在“interned”字符串表中输入 string 并返回 interned string - 它是字符串本身或副本。留置字符串对于在字典查找中获得一点性能很有用——如果字典中的键被留存,并且查找键被留存,则键比较(在散列之后)可以通过指针比较而不是字符串比较来完成。通常,Python 程序中使用的名称是自动实习的,用于保存模块、类或实例属性的字典具有实习键。

实习字符串不是不朽的;您必须保留对 intern() 的返回值的引用才能从中受益。

澄清

正如文档所暗示的,该sys.intern函数旨在用于性能优化

sys.intern函数维护一个内部字符串表。当您尝试实习字符串时,该函数会在表中查找它并:

  1. 如果字符串不存在(尚未被实习),该函数将其保存在表中并从实习字符串表中返回。

    >>> import sys
    >>> a = sys.intern('why do pangolins dream of quiche')
    >>> a
    'why do pangolins dream of quiche'
    

    在上面的示例中,a保存了实习字符串。即使它不可见,该sys.intern函数已将'why do pangolins dream of quiche'字符串对象保存在实习字符串表中。

  2. 如果字符串存在(已被实习),则函数从实习字符串表中返回它。

    >>> b = sys.intern('why do pangolins dream of quiche')
    >>> b
    'why do pangolins dream of quiche'
    

    即使它不是立即可见的,因为该字符串'why do pangolins dream of quiche'之前已被实习过,但b现在拥有与 相同的字符串对象a

    >>> b is a
    True
    

    如果我们在不使用实习生的情况下创建相同的字符串,我们最终会得到两个具有相同值的不同字符串对象。

    >>> c = 'why do pangolins dream of quiche'
    >>> c is a
    False
    >>> c is b
    False
    

通过使用sys.intern,您可以确保永远不会创建两个具有相同值的字符串对象——当您请求创建与现有字符串对象具有相同值的第二个字符串对象时,您会收到对预先存在的字符串对象的引用。这样,您就可以节省内存。此外,字符串对象比较现在非常有效,因为它是通过比较两个字符串对象的内存地址而不是它们的内容来执行的。

于 2009-07-16T11:02:23.027 回答
21

本质上,实习生在实习生字符串集合中查找(或存储,如果不存在)字符串,因此所有实习生实例将共享相同的身份。您将查找此字符串的一次性成本换成更快的比较(比较可以在检查身份后返回 True,而不必比较每个字符),并减少内存使用。

但是,python 会自动实习小字符串,或者看起来像标识符,所以你可能会发现你没有得到任何改进,因为你的字符串已经在幕后被实习了。例如:

>>> a = 'abc'; b = 'abc'
>>> a is b
True

过去,一个缺点是被保留的字符串是永久性的。一旦被实习,即使在所有引用都被删除后,字符串内存也永远不会被释放。我认为这不再是最新版本的 python 的情况。

于 2009-07-16T12:39:19.103 回答
10

他们不是在谈论关键字intern,因为 Python 中没有这样的东西。他们在谈论非必要的内置功能intern。py3k 中的哪个已移至sys.intern. 文档有详尽的描述。

于 2009-07-16T11:06:19.070 回答
4

它返回字符串的规范实例。

因此,如果您有许多相等的字符串实例,您可以节省内存,此外,您还可以通过身份而不是相等来比较规范化字符串,这样更快。

于 2009-07-16T10:59:36.587 回答