2017-05-16 48 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

这是一个很好的答案,尽管语言名称是令人不安的标签链接:) –