【发布时间】:2014-10-05 16:02:35
【问题描述】:
我正在尝试学习python在字符串对象实现中使用的实习机制。但是在PyObject *PyString_FromString(const char *str)和PyObject *PyString_FromStringAndSize(const char *str, Py_ssize_t size)这两个python中,只有当它的大小为0或1时才被困住。
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' 时创建了多个字符串,但没有'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”在哪里创建和实习?
更新 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]
【问题讨论】:
-
顺便说一句:你为什么要调查这个?这是一个非常不寻常的调查路线。
-
我认为这是一个有趣的问题,但是您以一种难以理解的方式提出了它。你应该在
a = 'python'和b == 'python'之后问为什么id(a) == id(b)。就您对 Python 源代码的理解而言,应该只保留长度为 0 和 1 的字符串。那么为什么'python'显然会被拘留? -
@zoujyjs 我看不出你的输出中有什么让你认为
'python'被拘留了。可能不是。但是编译代码中的文字可能引用同一个对象。 -
@NedBatchelder 因为这两个变量共享相同的内存地址。我通过修改 string_print 函数来打印它的地址。在 PyString_InternInPlace 中,如果我打印正在实习的对象,我可以在执行 cmd 时看到“Python”和许多其他对象。对不起格式,我用手机回复。
-
@DanielDarabos 看,你完全理解我了~ 为什么? ps:我已经更新了问题和标题。
标签: python python-c-api cpython