sys.intern() 做啥以及何时使用?

Posted

技术标签:

【中文标题】sys.intern() 做啥以及何时使用?【英文标题】:What does sys.intern() do and when should it be used?sys.intern() 做什么以及何时使用? 【发布时间】:2010-11-11 07:57:00 【问题描述】:

我遇到了this question关于字典的内存管理,其中提到了intern功能。它到底有什么作用,什么时候使用?

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

【问题讨论】:

我想把这篇文章放在这里,它还提供了关于这个非常好的问题的有趣示例和概念:levelup.gitconnected.com/… 【参考方案1】:

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

但是,python 会automatically intern strings that are small, or look like identifiers,所以你可能会发现你没有得到任何改进,因为你的字符串已经在幕后被实习了。例如:

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

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

【讨论】:

CPython 将自动实习小字符串——这是一种实现行为,不能保证所有实现都为真(但很可能是)。 CPython 将自动实习小字符串,但前提是它们是代码中的常量表达式,而不是在运行时创建的字符串。请参阅 ***.com/questions/15541404/python-string-interning。【参考方案2】:

来自Python 3 文档

sys.intern(string)

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

内部字符串不是不朽的;您必须保留对 intern() 的返回值可以从中受益。

澄清

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

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

    如果字符串不存在(还没有被实习)函数保存 它在表中并从实习字符串表中返回。

    >>> 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' 字符串对象保存在实习字符串表中。

    如果字符串存在(已被实习),则函数从 实习字符串表。

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

【讨论】:

如果我们将代码写入.py 文件并执行此操作,我们将得到c is a 作为True。这是为什么呢? @ShashankSingh 我的理解是,当 python 文件被编译成 PYC 文件时,它会在文件中创建一个常量列表,在这种情况下是字符串,并且它在任何地方出现而不是重新创建字符串指常数。因此,当读取文件时,所有出现的分配字符串 'why do ...' 分配给字符串的同一实例。【参考方案3】:

他们不是在谈论关键字intern,因为Python 中没有这样的东西。他们在谈论non-essential built-in function intern。 py3k 中的哪个已移至sys.intern。文档有详尽的描述。

【讨论】:

正确链接到 intern() 后 Python 文档 2 次:docs.python.org/2/library/functions.html#intern【参考方案4】:

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

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

【讨论】:

以上是关于sys.intern() 做啥以及何时使用?的主要内容,如果未能解决你的问题,请参考以下文章

IOCTL_DISK_VERIFY 做啥?

我可以有一个用于引用和指针的 ELI5 以及何时使用它们吗?

如何以及何时在 C# 中使用 :short?

int num = *(int *)number;这是做啥的?

NSUInteger vs NSInteger,int vs unsigned,以及类似情况

RewriteBase 做啥以及如何使用它?