我们怎样才能使一个类代表本身作为一个切片在适当的时候?
这并没有工作:
class MyThing(object):
def __init__(self, start, stop, otherstuff):
self.start = start
self.stop = stop
self.otherstuff = otherstuff
def __index__(self):
return slice(self.start, self.stop)
预期输出:
>>> thing = MyThing(1, 3, 'potato')
>>> 'hello world'[thing]
'el'
实际输出:
TypeError: __index__ returned non-(int,long) (type slice)
从slice
继承也不起作用。
TLDR:这是不可能让自定义类取代slice
为内建类型如list
和tuple
。
该方法__index__
纯粹的存在是为了提供一种索引,其是由定义在python的整数(参见the Data Model)。你不能用它解决的对象到slice
。
恐怕slice
似乎是由蟒蛇特殊处理。该接口要求的实际切片;提供它的签名(其也包括indices
方法)是不够的。正如你已经发现了,你不能继承它,所以你不能创建新类型slice
s的。即使是用Cython不会让你从它继承。
那么,为什么是slice
特别?很高兴你问。欢迎到CPython中的内脏。请阅读本后洗手。
所以切片对象在slice.rst
描述。请注意这两个家伙:
.. C:VAR :: PyTypeObject PySlice_Type
对于切片对象的类型的对象。这是相同的:类:在Python层
slice
。.. C:如果作业是切片对象函数:: INT PySlice_Check(的PyObject * 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语言实现没有什么是子类化,除非有人志愿者,使其子类化工作;没有人自告奋勇的工作,使[插入的名字在这里]类型子类化。这肯定不是我的名单眨眼的顶部。
另见this thread关于非subclass'able类型的一个简短的讨论。
几乎所有的替代口译复制行为在不同程度:Jython,Pyston,IronPython和PyPy(没搞清楚他们是如何做到这一点,但是他们这样做)。
I'M SORRY FOR THE DARK MAGIC
使用qazxsw POI和建造qazxsw POI方法我能做到这一点,Python的:
Forbiddenfruit
输出:
new
我写的是一个挑战,只是因为大家都说这是不可能的,我永远不会使用它的生产代码它有许多副作用,你应该重新考虑你的结构和需求
切片不能在你的from forbiddenfruit import curse
class MyThing(int):
def __new__(cls, *args, **kwargs):
magic_slice = slice(args[0], args[1])
curse(slice, 'otherstuff', args[2])
return magic_slice
thing = MyThing(1, 3, 'thing')
print 'hello world'[thing]
print thing.otherstuff
类型的方法就是不支持此功能。你可以阅读更多有关>>> el
>>> thing
return
。我只能拿出直接调用你的类功能的解决方法:
__index__
这将返回special method here。