我尝试在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)]'可以正常工作。 –