miracle2k
miracle2k

Reputation: 32087

How do you use the ellipsis slicing syntax in Python?

This came up in Hidden features of Python, but I can't see good documentation or examples that explain how the feature works.

Upvotes: 213

Views: 70048

Answers (5)

divenex
divenex

Reputation: 17236

When used with Numpy, the Ellipsis or ... allows one to write general functions that work for both 1-dimensional vectors and higher-dimensional arrays.

For example, suppose we want to write a (intentionally trivial) function that extracts a certain set of elements from every row of an array

def fun(arr):
    return arr[:, 1:4]

We create a 2-dim array

>>> import numpy as np
>>> a = np.arange(3*5).reshape(3, 5)
>>> a

array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])

The result of this function for the array a gives

>>> fun(a)

array([[ 1,  2,  3],
       [ 6,  7,  8],
       [11, 12, 13]])

However, if we now create a 1-dim vector b

>>> b =  np.arange(5)
>>> b

array([0, 1, 2, 3, 4])

The function throws an error for b because it only has one dimension

>>> fun(b)

IndexError: too many indices for array: array is 1-dimensional, but 2 were indexed

A general function that works for both vectors and arrays can be written using the Ellipsis or ... Numpy notation

def fun_ell(arr):
    return arr[..., 1:4]

Which works as expected for both the matrix (or higher-dimensional arrays) and the vector

>>> fun_ell(a)

array([[ 1,  2,  3],
       [ 6,  7,  8],
       [11, 12, 13]])

>>> fun_ell(b)

array([1, 2, 3])

This functionality is useful for more complex functions and is extensively used within the Numpy package.

Upvotes: 0

nosklo
nosklo

Reputation: 223102

Ellipsis, or ... is not a hidden feature, it's just a constant. It's quite different to, say, javascript ES6 where it's a part of the language syntax. No builtin class or Python language constuct makes use of it.

So the syntax for it depends entirely on you, or someone else, having written code to understand it.

Numpy uses it, as stated in the documentation. Some examples here.

In your own class, you'd use it like this:

>>> class TestEllipsis(object):
...     def __getitem__(self, item):
...         if item is Ellipsis:
...             return "Returning all items"
...         else:
...             return "return %r items" % item
... 
>>> x = TestEllipsis()
>>> print x[2]
return 2 items
>>> print x[...]
Returning all items

Of course, there is the python documentation, and language reference. But those aren't very helpful.

Upvotes: 137

Torsten Marek
Torsten Marek

Reputation: 86582

The ellipsis is used in numpy to slice higher-dimensional data structures.

It's designed to mean at this point, insert as many full slices (:) to extend the multi-dimensional slice to all dimensions.

Example:

>>> from numpy import arange
>>> a = arange(16).reshape(2,2,2,2)

Now, you have a 4-dimensional matrix of order 2x2x2x2. To select all first elements in the 4th dimension, you can use the ellipsis notation

>>> a[..., 0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

which is equivalent to

>>> a[:,:,:,0].flatten()
array([ 0,  2,  4,  6,  8, 10, 12, 14])

In your own implementations, you're free to ignore the contract mentioned above and use it for whatever you see fit.

Upvotes: 310

tzot
tzot

Reputation: 96051

This is another use for Ellipsis, which has nothing to do with slices: I often use it in intra-thread communication with queues, as a mark that signals "Done"; it's there, it's an object, it's a singleton, and its name means "lack of", and it's not the overused None (which could be put in a queue as part of normal data flow). YMMV.

Upvotes: 75

Mauricio Perez
Mauricio Perez

Reputation: 389

As stated in other answers, it can be used for creating slices. Useful when you do not want to write many full slices notations (:), or when you are just not sure on what is dimensionality of the array being manipulated.

What I thought important to highlight, and that was missing on the other answers, is that it can be used even when there is no more dimensions to be filled.

Example:

>>> from numpy import arange
>>> a = arange(4).reshape(2,2)

This will result in error:

>>> a[:,0,:]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array

This will work:

a[...,0,:]
array([0, 1])

Upvotes: 15

Related Questions