带有空格且末尾无空格且不可变的Python字符串


问题内容

我了解到,在一些一成不变的类,__new__可能会返回一个现有实例-这是什么intstr以及tuple各类有时小的值做。

但是,为什么以下两个片段的行为有所不同?

末尾有空格:

>>> a = 'string '
>>> b = 'string '
>>> a is b
False

没有空格:

>>> c = 'string'
>>> d = 'string'
>>> c is d
True

为什么空间带来差异?


问题答案:

这是关于CPython实现如何选择缓存字符串文字的古怪之处。具有相同内容的字符串文字可以引用相同的字符串对象,但不必如此。'string'恰好在时会自动被拦截,'string '因为并非'string'仅包含Python标识符中允许的字符。我不知道 为什么
这是他们选择的标准,但这是事实。在不同的Python版本或实现中,行为可能有所不同。

从CPython
2.7源代码的stringobject.h第28行:

中间字符串(ob_sstate)试图确保仅存在一个具有给定值的字符串对象,因此相等性测试可以是一个指针比较。尽管内置的intern()可用于强制对任何字符串进行中间化,但这通常仅限于“看起来像”
Python标识符的字符串。

您可以在中查看执行此操作的代码Objects/codeobject.c

/* Intern selected string constants */
for (i = PyTuple_Size(consts); --i >= 0; ) {
    PyObject *v = PyTuple_GetItem(consts, i);
    if (!PyString_Check(v))
        continue;
    if (!all_name_chars((unsigned char *)PyString_AS_STRING(v)))
        continue;
    PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i));
}

此外,请注意,实习是独立于Python字节码编译器合并字符串文字的独立过程。如果让编译器一起编译ab赋值,例如将它们放在模块或中if True:,则将发现ab相同的字符串。