带有空格且末尾无空格且不可变的Python字符串
问题内容:
我了解到,在一些一成不变的类,__new__
可能会返回一个现有实例-这是什么int
,str
以及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字节码编译器合并字符串文字的独立过程。如果让编译器一起编译a
和b
赋值,例如将它们放在模块或中if True:
,则将发现a
和b
相同的字符串。