TLDR:使用自定义类替换slice
的内置类型(如list
和tuple
)是不可能的。
的__index__
方法纯粹的存在是为了提供一种索引,其是由定义在python的整数(参见the Data Model)。您无法使用它将对象解析为slice
。
恐怕slice
似乎是由python专门处理。界面需要一个实际的切片;提供其签名(其中还包括indices
方法)是不够的。正如你发现的那样,你不能继承它,所以你不能创建新类型的slice
。即使Cython也不会让你继承它。
那么为什么slice
特别?很高兴你问。欢迎来到CPython的内部。阅读后请洗手。
所以切片对象在slice.rst
中描述。请注意这两个家伙:
。C:VAR :: PyTypeObject PySlice_Type
的切片对象的对象类型。这与Python层中的slice
类中的类: 相同。
.. c:function :: int PySlice_Check(PyObject * ob) 如果ob是切片对象,则返回true; ob一定不能是NULL。现在
,这sliceobject.h
实际上是实现为:
#define PySlice_Check(op) (Py_TYPE(op) == &PySlice_Type)
所以仅的slice
类型允许在这里。这个检查实际上用于list_subscript
(和tuple subscript
,...)之后试图使用索引协议(因此在片上有__index__
是个坏主意)。自定义容器类可以自由覆盖__getitem__
并使用其自己的规则,但这就是list
(和tuple
,...)这样做的方式。
现在,为什么不可能子类slice
?那么,type
实际上有一个标志,指示是否可以分类。检查here并产生你所看到的错误:
if (!PyType_HasFeature(base_i, Py_TPFLAGS_BASETYPE)) {
PyErr_Format(PyExc_TypeError,
"type '%.100s' is not an acceptable base type",
base_i->tp_name);
return NULL;
}
我一直无法追查slice
(UN)如何设置这个值,而是一个得到这个错误的事实意味着它。这意味着你不能继承它。
结束语:记住一些长期被遗忘的C-(非)-skills后,我相当肯定这是不是严格意义上的优化。所有现有的检查和技巧仍然有效(至少是我发现的)。
在洗完手和在互联网上四处挖掘之后,我发现了一些类似“问题”的参考。 Tim Peters has said all there is to say:
用C语言实现没有什么是子类化,除非有人志愿者工作 使它子类化;没有人自告奋勇地将[插入名称] 类型子分类。它肯定不在我的名单的顶部wink。
另请参阅this thread关于非子类类型的简短讨论。
几乎所有的替代口译复制行为在不同程度:Jython,Pyston,IronPython和PyPy(没搞清楚他们是如何做到这一点,但是他们这样做)。
好,从它看起来像'__index __()'强调返回一个'int'而不是'slice',并且它在返回单个整数时工作正常。 –
顺便说一句,你为什么要这么做? – MisterMiyagi
我正在制作一种应该像切片一样行为的丰富切片,但也有一些扩展功能。 – wim