在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基本上包含了接受的答案的第二部分,但存在语法错误,因此将其删除
答案 0 :(得分:1)
是的,您可以将任何类型的对象传递给slice
。 documentation没有提到对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]