2015-11-06 75 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