Python中的字符串是否会被池化?
Python中有没有一个字符串池,里面的字符串都是单例的?
更具体一点,在下面的代码中,内存里会创建一个字符串还是两个字符串呢?
a = str(num)
b = str(num)
4 个回答
2
字符串通常不会被“内部化”。在你的例子中,会创建两个字符串(0到9之间的值除外)。为了测试这一点,我们可以使用 is
操作符来检查这两个字符串是否是同一个对象:
>>> str(1056) is str(1056)
False
8
一般来说,在Python中字符串并不是总是被“内部化”的,但有时候看起来像是这样:
>>> str(5) is str(5)
True
>>> str(50) is str(50)
False
在Python中,这种情况并不少见,常见的对象可能会以某种方式进行优化,而不常见的对象则不会:
>>> int(5+0) is int(5+0)
True
>>> int(50+0) is int(50+0)
True
>>> int(500+0) is int(500+0)
False
另外要记住,这些细节在不同的Python版本和不同的实现之间会有所不同。
26
在Python中,字符串是不可改变的,这意味着一旦创建了字符串,它的内容就不能被修改。因此,程序可以选择是否将字符串存储在一个共享的地方,这个地方通常被称为“池”,这个概念在C#中比较常见。
在你的例子中,你是动态创建字符串。CPython并不是总是去这个池里查找字符串是否已经存在——这样做也没有意义,因为你首先需要为字符串预留内存,然后再和池里的内容进行比较(对于长字符串来说,这样做效率不高)。
但是,对于长度为1的字符串,CPython确实会去查找这个池(可以参考“stringobject.c”文件):
static PyStringObject *characters[UCHAR_MAX + 1];
...
PyObject *
PyString_FromStringAndSize(const char *str, Py_ssize_t size)
{
...
if (size == 1 && str != NULL &&
(op = characters[*str & UCHAR_MAX]) != NULL)
{
#ifdef COUNT_ALLOCS
one_strings++;
#endif
Py_INCREF(op);
return (PyObject *)op;
}
...
所以:
a = str(num)
b = str(num)
print a is b # <-- this will print False in most cases (but try str(1) is str(1))
不过,当你在代码中直接使用常量字符串时,CPython会使用同一个字符串实例:
a = "text"
b = "text"
print a is b # <-- this will print True