Why are non integral builtin types allowed in python slices?
<p>I've just improving test coverage for a <a href="https://github.com/JaggedVerge/mmap_backed_array" rel="nofollow">library</a> that has to support slices and I've noticed that slices can contain non-integral types:</p>

<pre><code>&gt;&gt;&gt; slice(1, "2", 3.0)
slice(1, '2', 3.0)
&gt;&gt;&gt; sl = slice(1, "2", 3.0)
&gt;&gt;&gt; [1,2,3][sl]
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: slice indices must be integers or None or have an __index__ method
</code></pre>

<p>This might just be my static-typing background but it seems strange to me that the builtin types without <code>__index__</code> can be passed in here without a <code>TypeError</code>. Why is this so? Would I be right in assuming that arbitrary types are allowed in order to support duck typing for types that implement <code>__index__</code>? Is the lack of a type check due to performance reasons for the most commonly used cases?</p>

<p>Prior to <a href="https://www.python.org/dev/peps/pep-0357/" rel="nofollow">PEP 357</a> was the slice in the example invalid?</p>

<blockquote>
  <p>Would I be right in assuming that arbitrary types are allowed in order to support duck typing for types that implement <code>__index__</code>?</p>
</blockquote>

<p>There's no actual reason as to why you should restrict the types passed when initializing <code>slice</code> objects. Exactly as stated in the rational for <code>PEP 357</code>, <code>numpy</code> and the numeric types it utilizes can't inherit from object so strict <code>issubclass</code> checks of the type passed will make them unusable as index values. So duck typing is employed, if it defines the appropriate method (<code>__index__</code>), it's usable.</p>

<p>Also take note that this (the presence of <code>__index__</code>) is enforced only when applying the slice (as you saw, the <code>TypeError</code> was raised during the <code>__getitem__</code>, i.e <a href="https://github.com/python/cpython/blob/master/Objects/sliceobject.c#L194" rel="nofollow"><code>list_subscript</code></a> ) operation when <a href="https://github.com/python/cpython/blob/master/Objects/sliceobject.c#L114" rel="nofollow"><code>PySlice_GetIndicesEx</code></a> is called to try and get the values you passed.</p>

<p>The <a href="https://github.com/python/cpython/blob/master/Objects/sliceobject.c#L114" rel="nofollow">slice objects initializer</a> makes no discrimination on what type it accepts, all <code>PyObject</code>'s can apply as can be seen from its signature:</p>

<pre><code>PyObject *
PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
{
   /* rest omitted */
</code></pre>

<blockquote>
  <p>Prior to <code>PEP 357</code> was the slice in the example invalid?</p>
</blockquote>

<p>I just built a <code>2.4</code> version of Python and tested it (<code>PEP 357</code> appeared in <code>2.5</code> if I'm not mistaken), again the check if the arguments are numeric is not done during initialization but when <code>__getitem__</code> is invoked; the only thing that differs is the exception message which doesn't make any notice about the <code>__index__</code> dunder (which then obviously didn't exist):</p>

<pre><code>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.
&gt;&gt;&gt; s = slice(0, Ellipsis)
&gt;&gt;&gt; [1, 2, 3][s]
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in ?
TypeError: slice indices must be integers
</code></pre>

python python-3.x slice python-internals