Как вы используете синтаксис нарезки многоточия в Python?

Ответы:

102

Ellipsis, или ... это не скрытая функция, это просто константа. Это совсем не то, что, скажем, javascript ES6, где он является частью синтаксиса языка. Ни один встроенный класс или языковая структура Python не используют его.

Таким образом, синтаксис этого полностью зависит от вас, или кто-то еще, написав код, чтобы понять это.

Numpy использует его, как указано в документации . Некоторые примеры здесь .

В вашем собственном классе вы бы использовали это так:

>>> 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

Конечно, есть документация по питону и языковая справка . Но это не очень полезно.

nosklo
источник
6
выглядит довольно испорченным, так как «пропер» способ сказать, что все элементы >>> x [:] >>> x [:, 1: 2]
Ронни
30
@Ronny: Смысл был в том, чтобы продемонстрировать использование Ellipsis.
Носкло
7
Ссылки кажутся неработающими.
SwiftsNamesake
231

Многоточие используется для нарезки многомерных структур данных.

На данный момент: он предназначен для вставки как можно большего количества полных срезов ( ), чтобы расширить многомерный срез до всех измерений .

Пример :

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

Теперь у вас есть 4-мерная матрица порядка 2x2x2x2. Чтобы выбрать все первые элементы в 4-м измерении, вы можете использовать многоточие

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

что эквивалентно

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

В ваших собственных реализациях вы можете свободно игнорировать контракт, упомянутый выше, и использовать его по своему усмотрению.

Торстен Марек
источник
Может быть, я ошибаюсь, но разве это a[:,:,:,0]не вернет копию и a[...,0]вернет «представление», а не копию? Я попытался запустить id()обе версии и массив 3-dim: у a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] всех разные идентификаторы, тогда как у a[..., 0], a[..., 1], a[..., 2] всех одинаковые идентификаторы.
mohitsharma44
@ mohitsharma44 не на моей машине;) id()возвращает одинаковое значение для обоих. Также проверка с __array_interface__['data']показывает тот же адрес памяти.
BoltzmannBrain
Я считаю, что мы можем использовать в a[indexes, ...]то время как даже одномерный массив!
Активист
1
Эллипсы также полезны для нульмерных структур данных. Это единственный известный мне способ записи в скалярные numpy.ndarrays, например: my_scalar = np.asarray (3); my_scalar [...] = 5. Если вы выполните my_scalar [:] = 5, вы по праву получите ошибку, потому что нет измерения 0 для итерации.
SuperElectric
1
@SuperElectric Вы также можете использовать my_scalar.itemset (scalarvalue). Конечно, my_scalar [...] = scalar_value короче, но вы сказали в комментарии выше, что это единственный способ узнать. Просто даю альтернативу.
kamathln
70

Это еще одно использование Ellipsis, которое не имеет ничего общего со срезами: я часто использую его для связи между потоками внутри потока, как знак, обозначающий «Готово»; это там, это объект, это одиночный объект, и его имя означает «отсутствие», и это не чрезмерное None (которое может быть помещено в очередь как часть обычного потока данных). YMMV.

tzot
источник
14
Разве не было бы яснее просто сказать: "Done = object ()" где-нибудь и просто использовать это?
Брэндон Родс
12
Не обязательно - требуется, чтобы вы на самом деле где-то сказали Done = object (). Значения Sentinel не обязательно являются плохой вещью - и использование практически бесполезных синглтонов Python в качестве часовых не так уж и ужасно для IMO (Ellipsis и () - это те, которые я использовал, где None может сбить с толку).
Рик Коупленд
6
Что касается Done = object (), я думаю, что лучше использовать Ellipsis, особенно если вы используете его для связи с очередями. Если вы переходите от внутрипотокового к внутрипроцессному взаимодействию, id (Готово) не будет одинаковым в другом процессе, и ничто не будет отличать один объект от другого. Идентификатор Ellipsis тоже не будет прежним, но, по крайней мере, тип будет таким же - это точка синглтона.
Тристан Рейд
Вопрос говорит: «Как вы используете многоточие», но я считаю, что вы поняли это неправильно. У этого есть много интерпретаций. Но я думаю, что правильно: «Как используется многоточие?» т.е. «Какие шаги я должен предпринять, чтобы использовать Ellipsis в моем собственном коде».
Линдон Уайт
6

Как указано в других ответах, его можно использовать для создания слайсов. Полезно, когда вы не хотите писать много нотаций с полными срезами ( :), или когда вы просто не уверены, какова размерность манипулируемого массива.

То, что я считал важным выделить, и чего не хватало в других ответах, это то, что его можно использовать даже тогда, когда нет больше измерений, которые необходимо заполнить.

Пример:

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

Это приведет к ошибке:

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

Это будет работать:

a[...,0,:]
array([0, 1])
Маурисио Перес
источник