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