Jam*_*pam 9 python string cpython immutability python-internals
我了解到,在一些一成不变的类,__new__可能会返回一个现有实例-这是什么int,str以及tuple各类有时小的值做.
但为什么以下两个片段的行为不同?
最后有一个空格:
>>> a = 'string '
>>> b = 'string '
>>> a is b
False
Run Code Online (Sandbox Code Playgroud)
没有空间:
>>> c = 'string'
>>> d = 'string'
>>> c is d
True
Run Code Online (Sandbox Code Playgroud)
为什么空间带来了差异?
use*_*ica 14
这是CPython实现如何选择缓存字符串文字的一个怪癖.具有相同内容的字符串文字可以引用相同的字符串对象,但它们不必.'string'碰巧'string '是因为不'string'包含因为只包含Python标识符中允许的字符而自动实现.我不知道为什么这是他们选择的标准,但确实如此.在不同的Python版本或实现中,行为可能不同.
从CPython 2.7源代码stringobject.h,第28行:
实习字符串(ob_sstate)尝试确保只存在一个具有给定值的字符串对象,因此相等测试可以是一个指针比较.这通常仅限于"看起来像"Python标识符的字符串,尽管intern()内置可用于强制任何字符串的实习.
您可以在以下位置查看执行此操作的代码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));
}
Run Code Online (Sandbox Code Playgroud)
另请注意,实习是与Python字节码编译器合并字符串文字的单独过程.如果你让编译器一起编译a和b赋值,例如将它们放在一个模块或一个模块中if True:,你就会发现它a并且b是相同的字符串.
这种行为并不一致,正如其他人所提到的那样取决于正在执行的Python的变体.有关更深入的讨论,请参阅此问题.
如果要确保使用相同的对象,可以通过适当的命名强制执行字符串的实际操作intern:
实习生(...)实习生(字符串) - >字符串
Run Code Online (Sandbox Code Playgroud)``Intern'' the given string. This enters the string in the (global) table of interned strings whose purpose is to speed up dictionary lookups. Return the string itself or the previously interned string object with the same value.
>>> a = 'string '
>>> b = 'string '
>>> id(a) == id(b)
False
>>> a = intern('string ')
>>> b = intern('string ')
>>> id(a) == id(b)
True
Run Code Online (Sandbox Code Playgroud)
请注意,在Python3中,您必须显式导入实习生from sys import intern.