我刚刚改进了必须支持切片的library的测试覆盖率,并且我注意到切片可以包含非整数类型:
>>> slice(1, "2", 3.0)
slice(1, '2', 3.0)
>>> sl = slice(1, "2", 3.0)
>>> [1,2,3][sl]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: slice indices must be integers or None or have an __index__ method这可能只是我的静态类型背景,但对我来说似乎很奇怪,没有__index__的内置类型可以在没有TypeError的情况下传入。为何会这样呢?我假设允许任意类型以支持实现__index__的类型的鸭子类型,这样做对吗?在最常用的情况下,缺少类型检查是否是由于性能原因?
在PEP 357之前,示例中的切片是否无效?
发布于 2016-09-12 01:48:57
第三方库可能希望为它们自己的对象实现切片,并且核心语言没有理由限制这些第三方库在它们的切片中仅使用整数或类似整数的对象(即,其类型提供__index__方法的对象)。这里有两个在切片中使用非整数的包的值得注意的示例:在NumPy中,一些对象接受复杂的步骤,例如:
>>> import numpy
>>> numpy.mgrid[0:2:5j]
array([ 0. , 0.5, 1. , 1.5, 2. ])在Pandas中,您可以按标签对Series或Dataframe对象进行切片。该标签可以是字符串,也可以是datetime对象(例如)。
>>> import pandas
>>> s = pandas.Series(range(4), index=['a', 'b', 'c', 'd'])
>>> s['b':'d']
b 1
c 2
d 3
dtype: int64因此,对于核心语言来说,在构造包含非整数的切片时引发异常是没有意义的;这会破坏上面的库。相反,如果切片组件(start、stop、step)不属于适当的类型,则实际的切片操作应引发异常。
发布于 2016-09-11 22:41:03
为了支持实现__index__的类型的
类型,我假设允许任意类型是否是正确的?
在初始化slice对象时,没有实际的理由来说明为什么要限制传递的类型。正如rational for PEP 357中声明的那样,numpy和它使用的数值类型不能从object继承,所以对传递的类型进行严格的issubclass检查将使它们不能用作索引值。所以使用了鸭子类型,如果它定义了适当的方法(__index__),它就是可用的。
还要注意,只有在应用切片(如您所见,TypeError是在__getitem__操作期间引发的,即list_subscript )时,才会强制执行此操作(存在PySlice_GetIndicesEx ),此时会调用PySlice_GetIndicesEx来尝试获取您传递的值。
slice objects initializer不区分它接受的类型,所有的PyObject都可以应用,从它的签名可以看出:
PyObject *
PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
{
/* rest omitted */在PEP 357之前,
示例中的切片是否无效?
我刚刚构建了一个2.4版本的Python并对其进行了测试(如果我没记错的话,PEP 357出现在2.5中),同样,检查参数是否为数字的检查不是在初始化期间完成的,而是在调用__getitem__时完成的;唯一不同的是没有注意到__index__ dunder的异常消息(当时显然还不存在):
Python 2.4 (#1, Sep 11 2016, 18:13:11)
[GCC 5.4.0 20160609] on linux4
Type "help", "copyright", "credits" or "license" for more information.
>>> s = slice(0, Ellipsis)
>>> [1, 2, 3][s]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: slice indices must be integershttps://stackoverflow.com/questions/39433018
复制相似问题