我嘗試在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)
返回了一個空字符串。爲什麼這樣?
我嘗試在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)
返回了一個空字符串。爲什麼這樣?
字符串在c實現這樣的答案是不是直接的瞭解,如果你不知道很多關於c和python-c-api,但我盡我所能,反正:
如果您直接致電__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
是停止索引。如果停止小於零,它將被設置爲0
(if (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__
很久以前就被棄用了 - 更好地遠離它。
這是一個很好的答案,儘管語言名稱是令人不安的標籤鏈接:) –
這不是特定於字符串;你用'foo = list(foo)'得到相同的行爲。另外,對於'str'和'list','help(* .__ getslice __)'明確提到不支持負索引。 'foo [slice(10,-1)]'可以正常工作。 –