2017-05-16 79 views
4

我嘗試在Python 2.7運行下面的代碼getslice__不工作:海峽.__預期負停止

foo = "python is awesome" 
print foo[10:16] 
print foo.__getslice__(10,16) 
print foo[10:-1] 
print foo.__getslice__(10,-1) 

所有除最後一個印刷"awsome"。但foo.__getslice__(10,-1)返回了一個空字符串。爲什麼這樣?

+2

這不是特定於字符串;你用'foo = list(foo)'得到相同的行爲。另外,對於'str'和'list','help(* .__ getslice __)'明確提到不支持負索引。 'foo [slice(10,-1)]'可以正常工作。 –

回答

4

字符串在實現這樣的答案是不是直接的瞭解,如果你不知道很多關於,但我盡我所能,反正:

如果您直接致電__getslice__你會使用string_slice

static PyObject * 
string_slice(PyStringObject *a, Py_ssize_t i, Py_ssize_t j) 
    /* j -- may be negative! */ 
{ 
    if (i < 0) 
     i = 0; 
    if (j < 0) 
     j = 0; /* Avoid signed/unsigned bug in next line */ 
    if (j > Py_SIZE(a)) 
     j = Py_SIZE(a); 
    if (i == 0 && j == Py_SIZE(a) && PyString_CheckExact(a)) { 
     /* It's the same as a */ 
     Py_INCREF(a); 
     return (PyObject *)a; 
    } 
    if (j < i) 
     j = i; 
    return PyString_FromStringAndSize(a->ob_sval + i, j-i); 
} 

這裏i是開始索引和j是停止索引。如果停止小於零,它將被設置爲0if (j < 0) j = 0;),然後因爲它比起始點小,所以它將被設置爲開始(if (j < i) j = i;)。所以你最終得到了start = 10和stop = 10,這只是一個空字符串。

但是如果你使用[]你會打電話給string_subscript(我只包括方法的相關部分):

static PyObject* 
string_subscript(PyStringObject* self, PyObject* item) 
{ 
    /* ... */ 
    if (PySlice_Check(item)) { 
     Py_ssize_t start, stop, step, slicelength, cur, i; 
     /* ... */ 

     if (_PySlice_Unpack(item, &start, &stop, &step) < 0) { 
      return NULL; 
     } 
     slicelength = _PySlice_AdjustIndices(PyString_GET_SIZE(self), &start, 
              &stop, step); 

     /* ... */ 
     if (step == 1) { 
      return PyString_FromStringAndSize(
       PyString_AS_STRING(self) + start, 
       slicelength); 
     } 
     /* ... */ 
    } 
    /* ... */ 
} 

正確調整與_PySlice_AdjustIndices指數(它像PySlice_AdjustIndices)。該函數將-1的止動轉換成的len(string) - 1停止:

Py_ssize_t PySlice_AdjustIndices(Py_ssize_t長度,Py_ssize_t *開始,Py_ssize_t *停止,Py_ssize_t步驟)

調整開始/結束的切片索引假定一個指定長度的序列。越界索引以與正常切片處理一致的方式被裁剪。

實際調用的函數可能與該函數不同。但我相信這些文件適用於兩者。


但是,您通常不應該直接調用__*__方法。所以我不知道這是否是Python中的一個錯誤或預期用途(對於我所知道的某種切片,它可能是一個優化函數)。

但是__getslice__很久以前就被棄用了 - 更好地遠離它。

+1

這是一個很好的答案,儘管語言名稱是令人不安的標籤鏈接:) –