字符串 split() 的身份怪癖

one*_*ece 5 python string primitive split

>>> 'hi'.split()[0] is 'hi'
    True    
>>> 'hi there'.split()[0] is 'hi'
    False
>>> 'hi there again'.split()[0] is 'hi'
    False
Run Code Online (Sandbox Code Playgroud)

我的假设:

第一行只有一个被拆分的元素,而另外两行有多个元素。我相信,虽然像 Python 原语这样str的函数是按值存储在内存中的,但函数之间会有单独的分配,以简化内存管理。我认为split()是这些函数之一,它通常分配新的字符串。但它也处理不需要任何拆分的输入的边缘情况(例如'hi'),其中仅返回原始字符串引用。我的解释正确吗?

use*_*ica 1

我相信,虽然像 str 这样的 Python 原语是按函数内的值存储在内存中的,但跨函数将会有单独的分配,以简化内存管理。

Python 的对象分配不会像这样工作。没有真正的“基元”概念,除了字节码编译器执行的一些合并常量的操作之外,两个对象是在同一函数还是不同函数中创建并不重要。

对于这个问题,没有比指出来源更好的答案了,所以这里是

Py_LOCAL_INLINE(PyObject *)
STRINGLIB(split_whitespace)(PyObject* str_obj,
                           const STRINGLIB_CHAR* str, Py_ssize_t str_len,
                           Py_ssize_t maxcount)
{
    ...
#ifndef STRINGLIB_MUTABLE
        if (j == 0 && i == str_len && STRINGLIB_CHECK_EXACT(str_obj)) {
            /* No whitespace in str_obj, so just use it as list[0] */
            Py_INCREF(str_obj);
            PyList_SET_ITEM(list, 0, (PyObject *)str_obj);
            count++;
            break;
        }
Run Code Online (Sandbox Code Playgroud)

如果它找不到任何空白来分割,它只会重用返回列表中的原始字符串对象。这只是此函数编写方式的一个怪癖,您不能依赖它在其他 Python 版本或非标准 Python 实现中以这种方式工作。

  • @gkusner:在我看来,提问者已经明白了这一点。该问题具体询问了对象分配策略,并且没有提及对于相等的字符串“x”和“y”,“x is y”应该为真的任何期望。 (2认同)