2015-11-06 34 views
4
>>> 'hi'.split()[0] is 'hi' 
    True  
>>> 'hi there'.split()[0] is 'hi' 
    False 
>>> 'hi there again'.split()[0] is 'hi' 
    False 

我的假设:身份与字符串分割()怪癖

第一行中只有一个分割元件,而其他两个有一个以上的元素。我相信尽管Python原语(如str)通过函数内的值存储在内存中,但跨函数的分配会简化内存管理。我认为split()是这些函数之一,它通常分配新的字符串。但它也处理不需要任何拆分的输入的边界情况(如'hi'),其中原始字符串引用仅返回。我的解释是否正确?

+0

否,原因是“是”是指相同的存储器位置它与'=='不一样,将你的比较改为==,它们会正常工作,'是'应该只用于比较静态内存中的元素,比如None。True/False – gkusner

回答

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

这是一个很好的答案 - 但所有这些的真正意义应该是指出显而易见的 - 不要使用'是'比较字符串 - 使用'==' – gkusner

+2

@gkusner:看起来像提问者已经理解这一点。这个问题特别提到了对象分配策略,并没有提到任何期望“x是y”应该对于相同的字符串“x”和“y”是真实的。 – user2357112

0

所以像我在评论说:

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

>>True 

其实你的问题那种钉它 - 这是一个身份。

+1

你没有真正回答关于'split()'的问题,为什么一个元素将具有相同的内存位置,但多个元素不会。是否因为每个函数都有自己的原始分配? – onepiece

+0

本质上是字符串区域被哈希以保持重复,所以字符串Hi只存储一次 – gkusner

0

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

(与Java具有明显不同的数据类型为“原语”和“参考/类类型”,并与他们的行为不同)

+0

嗯,我现在正在学Java,不知道这个;那很有意思。很好的解释。 – Saroekin