16

Python 是否有一个包含所有字符串的池,它们是(字符串)单例吗?

更准确地说,在下面的代码中,是在内存中创建了一个还是两个字符串?

a = str(num)
b = str(num)
4

4 回答 4

24

字符串在 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
于 2010-03-25T21:40:19.030 回答
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 的实现之间会有所不同,甚至在同一实现的不同版本之间也会有所不同。

于 2010-03-25T21:40:55.113 回答
2

字符串通常不被实习。在您的示例中,将创建两个字符串(0 到 9 之间的值除外)。为了测试这一点,我们可以使用is运算符来查看两个字符串是否是同一个对象:

>>> str(1056) is str(1056)
False
于 2010-03-25T21:35:09.983 回答
0

python中pool的常量区分小整数池和大整数池,小整数池的范围在[-5, 257);和大整数池中的其他整数。在 Cython 中,如果定义了一个链表来存储这些数据,那么获取数据就变得非常方便快捷。

# ifndef NSMALLPOSINTS
    # define NSMALLPOSINTS 257
# endif

# ifndef NSMALLNEGINTS
    # define NSMALLNEGINTS 5
# endif

# if NSMALLPOSINTS + NSMALLNEGINTS > 0
    static PyIntObject * small_ints[NSMALLPOSINTS + NSMALLNEGINTS];
# endif

顺便说一句:整数 257 可能比较陌生;如果两个具有相同值的对象在同一个字段中,它们的地址可能相同也可能不同,这取决于进程的上下文;而如果它们在不同的字段中,则它们的地址必须不同

顺便说一下,根据字符串类型,cython还提供了一个常量池,字符串的长度应该是1,而它可能不是同一个对象

a = str(11)
b = str(11)
print a == b      # True 
print a is b      # False

c = str("A")
d = str("A")   
print c == d    # True
print c is d    # True

aa = 12
bb = 12
print aa == bb    # True
print aa is bb    # True

cc = 333
dd = 333
print cc == dd    # True
print cc is dd    # False

比较他们的地址,显然是领先的解决方案

于 2018-09-07T08:25:02.283 回答