何时以及如何将slice(obj)用于非int / None类型?

时间:2018-10-25 14:11:55

标签: python python-3.x range slice

在Python 3中,以下代码不会产生错误:

slice(10.0)

同时执行以下操作:

range(10.0)

如果我尝试使用slice(float)对象,它也会失败:

list(range(20))[slice(10.0)]

,出现以下错误:

  

TypeError: slice indices must be integers or None or have an __index__ method

表示slice()可与实现__index__方法的其他对象一起使用。

何时/如何将slice(obj)用于非int / None类型?

为什么在实例化float对象时允许使用slice()个数字? 我可以依靠slice(float)(以及slice(float, float)slice(float, float, float))从不抱怨Python 3中的实例化吗?

编辑:

这似乎与PEP357 https://docs.python.org/2.5/whatsnew/pep-357.html

有关

但是,除了在NumPy中实现高级索引的实现之外,我还不清楚它是否还有其他用途。

EDIT3:EDIT2基本上包含了接受的答案的第二部分,但存在语法错误,因此将其删除

1 个答案:

答案 0 :(得分:1)

是的,您可以将任何类型的对象传递给slicedocumentation没有提到对slice的参数类型的限制,而source code for slice's constructor只说“ start,stop和step是python对象”。

list(range(20))[slice(10.0)]拒绝具有浮点参数的切片对象,但这似乎特定于列表类型。数据模型本身在调用__getitem__之前不进行隐式类型检查。您可以编写自己的自定义类,以接受更多非常规切片。示例:

>>> class Fred:
...     def __getitem__(self, idx):
...         return "baz"
...
>>> x = Fred()
>>> print(x[slice("Foo", "Bar")])
baz
>>> print(x[1.0: -10.5])
baz

关于是否有实际理由允许使用非整数切片,没有人想到……但是Python社区有一个文化规范,即“我们都是成年人”。就是说,不应仅仅因为没有明显的实际应用而禁止某些事情。如果某人想做一件看起来很愚蠢的事情,那么在其他所有事情都一样的情况下,我们应该让他们这样做。


我们已经确定,用户定义的类型可以接受他们想要的任何类型的切片。但是,如果您希望能够用不寻常的切片对内置类型进行切片呢?您不能更改列表类型的实现以删除对其进行检查的类型。 __index__可以方便地定义可用于切片列表的新类型。例如,

>>> class Begin:
...     def __index__(self):
...         return 0
...
>>> class End:
...     def __index__(self):
...         return -1
...
>>> list(range(20))[slice(Begin(), End())]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]