为什么在执行 `a = 'python'` 时 python 会驻留字符串,而源代码没有显示这一点?

2023-12-11

我正在尝试学习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]

字符串文字被编译器转换为字符串对象。执行此操作的函数是PyString_DecodeEscape,至少在Py2.7中,你还没有说你正在使用什么版本。

Update:

编译器在编译期间会实习一些字符串,但是当它发生时会非常混乱。该字符串只需包含标识符确定字符:

>>> a = 'python'
>>> b = 'python'
>>> a is b
True
>>> a = 'python!'
>>> b = 'python!'
>>> a is b
False

即使在函数中,字符串文字也可以被保留:

>>> def f():
...   return 'python'
...
>>> def g():
...   return 'python'
...
>>> f() is g()
True

但如果他们有有趣的角色则不然:

>>> def f():
...   return 'python!'
...
>>> def g():
...   return 'python!'
...
>>> f() is g()
False

如果我返回一对字符串,则它们都不会被保留,我不知道为什么:

>>> def f():
...   return 'python', 'python!'
...
>>> def g():
...   return 'python', 'python!'
...
>>> a, b = f()
>>> c, d = g()
>>> a is c
False
>>> a == c
True
>>> b is d
False
>>> b == d
True

这个故事的寓意是:实习是一种依赖于实现的优化,取决于许多因素。了解它的工作原理可能很有趣,但永远不要依赖它以任何特定的方式工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么在执行 `a = 'python'` 时 python 会驻留字符串,而源代码没有显示这一点? 的相关文章

随机推荐