为什么以及在执行`a =' python'`时python实现了字符串,而源代码没有显示?

时间:2014-08-12 14:21:36

标签: python python-c-api cpython

我正在尝试在字符串对象的实现中学习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来打印地址,则它与另一个字符串varable b = 'python相同。在上面标记为[1]的行中,当python创建一个字符串对象时,我打印一段日志,显示在没有'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'在哪里被创建和实习?

更新1

Plz参考@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]

1 个答案:

答案 0 :(得分:3)

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

更新

编译器在编译期间会对某些字符串进行实例化,但是当它发生时会非常混乱。字符串只需要包含identifier-ok字符:

>>> 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

故事的道德:实习是依赖于实现的优化,取决于许多因素。理解它是如何工作的可能很有趣,但从不依赖它以任何特定的方式工作。