字符串拆分的身份怪癖()

时间:2015-11-06 19:45:04

标签: python string split primitive

>>> 'hi'.split()[0] is 'hi'
    True    
>>> 'hi there'.split()[0] is 'hi'
    False
>>> 'hi there again'.split()[0] is 'hi'
    False

我的假设:

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

3 个答案:

答案 0 :(得分:1)

  

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

Python的对象分配不起作用。没有一个真实的“原语”概念,除了字节码编译器合并常量的一些事情外,在同一个函数或不同的函数中创建两个对象并不重要。

对于这一点,没有比指向源更好的答案,所以here it is

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

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

答案 1 :(得分:0)

就像我在评论中说的那样:

'hi there again'.split()[0] == 'hi'

>>True

实际上你的问题就是把它钉在上面 - 这是一种身份。

答案 2 :(得分:0)

Python中的所有数据都是通过引用存储的。 (C实现中的PyObject*)您发现的是.split()仅在找不到分隔符时返回self作为优化。找到分隔符时,它必须为每个部分创建单独的字符串对象,因此它们是单独的对象。

(与“基元”和“参考/类类型”具有截然不同的数据类型的Java不同,并且与它们的行为不同)