Python实习字符串吗?

Python实习字符串吗?,python,memoization,string-interning,Python,Memoization,String Interning,在Java中,显式声明的字符串被JVM占用,因此相同字符串的后续声明将导致指向相同字符串实例的两个指针,而不是两个单独(但相同)的字符串 例如: public String baz() { String a = "astring"; return a; } public String bar() { String b = "astring" return b; } public void main() { String a = baz() St

在Java中,显式声明的字符串被JVM占用,因此相同字符串的后续声明将导致指向相同字符串实例的两个指针,而不是两个单独(但相同)的字符串

例如:

public String baz() {
    String a = "astring";
    return a;
}

public String bar() {
    String b = "astring"
    return b;
}

public void main() {
    String a = baz()
    String b = bar()
    assert(a == b) // passes
}
我的问题是,CPython(或任何其他Python运行时)是否对字符串执行相同的操作?例如,如果我有一些课程:

class example():
    def __init__():
        self._inst = 'instance' 

然后创建这个类的10个实例,它们中的每一个都会有一个引用内存中相同字符串的实例变量,还是最终会有10个单独的字符串?

这称为interning,是的,Python在某种程度上会这样做,对于创建为字符串文本的较短字符串。有关讨论,请参阅

实习依赖于运行时,没有标准。在内存使用和检查是否创建相同字符串的成本之间,实习总是一种折衷。如果您有这种倾向,有一种方法可以强制解决这个问题,其中记录了一些实习Python自动为您做的事情:

通常,Python程序中使用的名称会自动插入,用于保存模块、类或实例属性的字典具有插入键


请注意,Python2的
intern()
函数过去是一个内置函数,无需导入。

一个相当简单的方法是使用
id()
。然而,正如@MartijnPieters提到的,这取决于运行时

class example():

    def __init__(self):
        self._inst = 'instance'

for i in xrange(10):
    print id(example()._inst)
  • 所有长度为0和长度为1的字符串都被插入
  • 字符串在编译时被暂存('wtf'将被暂存,但''联接(['w','t','f']将不被暂存)
  • 不是由ASCII字母、数字或下划线组成的字符串不会被保留。这就解释了为什么“wtf!”由于!而没有保留


上面的文章解释了python中的字符串插入。文章中明确定义了一些例外情况。

一些字符串插入python中。在编译python代码时,插入了标识符,例如变量名、函数名、类名

符合标识符规则(以下划线或字符串开头且仅包含下划线、字符串和数字)的字符串将被插入:

a="hello"
b="hello"
由于字符串是不可变的,因此python在此处和此处共享内存引用

a is b ===> True
但是如果我们有

a="hello world"
b="hello world"
因为“hello world”不符合标识符规则,所以a和b不被实习

a is b  ===> False
您可以使用
sys.intern()
对这些字符串进行intern。如果代码中有大量字符串重复,请使用此方法

a=sys.intern("hello world")
b=sys.intern("hello world")
现在
a是b==>真的

请注意,Python 3中内置的
intern
似乎已被删除。我现在不想确切了解哪个版本。@zwol:3.0。我会看看是否能找到动机,可能是在某个地方的PEP中。@zwol:它已被移动到
sys
模块。密切相关: