我正在尝试学习Python在字符串对象的实现中使用的实习生机制。但在两者中PyObject *PyString_FromString(const char *str)
andPyObject *PyString_FromStringAndSize(const char *str, Py_ssize_t size)
仅当字符串大小为 0 或 1 时,Python 才会对字符串进行内部处理。
PyObject *
PyString_FromString(const char *str)
{
fprintf(stdout, "creating %s\n", str);------------[1]
//...
//creating...
/* share short strings */
if (size == 0) {
PyObject *t = (PyObject *)op;
PyString_InternInPlace(&t);
op = (PyStringObject *)t;
nullstring = op;
Py_INCREF(op);
} else if (size == 1) {
PyObject *t = (PyObject *)op;
PyString_InternInPlace(&t);
op = (PyStringObject *)t;
characters[*str & UCHAR_MAX] = op;
Py_INCREF(op);
}
return (PyObject *) op;
}
但对于较长的字符串,例如a ='python'
,如果我修改了string_print
要打印地址,它与另一个字符串变量的地址相同b = 'python
。在上面标记为[1]的行,当python创建一个字符串对象时,我打印了一条日志,显示执行时创建了多个字符串a ='python'
只是没有“蟒蛇”。
>>> a = 'python'
creating stdin
creating stdin
string and size creating (null)
string and size creating a = 'python'
?
creating a
string and size creating (null)
string and size creating (null)
creating __main__
string and size creating (null)
string and size creating (null)
creating <stdin>
string and size creating d
creating __lltrace__
creating stdout
[26691 refs]
creating ps1
creating ps2
那么字符串“python”是在哪里创建和保留的呢?
Update 1
请参阅@Daniel Darabos 的评论以获得更好的解释。这是一种更容易理解的方式来问这个问题。
以下是输出PyString_InternInPlace
添加日志打印命令后。
PyString_InternInPlace(PyObject **p)
{
register PyStringObject *s = (PyStringObject *)(*p);
fprintf(stdout, "Interning ");
PyObject_Print(s, stdout, 0);
fprintf(stdout, "\n");
//...
}
>>> x = 'python'
Interning 'cp936'
Interning 'x'
Interning 'cp936'
Interning 'x'
Interning 'python'
[26706 refs]