Як ви використовуєте синтаксис нарізки еліпсису в 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

Звичайно, є і пітон документація , і мова . Але це не дуже допомагає.


6
виглядає досить розбитим, оскільки "пропперний" спосіб сказати всі предмети - >>> x [:] >>> x [:, 1: 2]
Ронні

30
@Ronny: Справа в тому, щоб продемонструвати певне користування Еліпсісом.
nosklo

7
Здається, посилання розірвані.
SwiftsNamesake

231

Еліпсис використовується в нумері для зрізування структур більш високих розмірів даних.

Він призначений означати, що в цей момент вставити стільки повних фрагментів ( :), щоб розширити багатовимірний фрагмент на всі виміри .

Приклад :

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

Тепер у вас є 4-мірна матриця порядку 2х2х2х2. Для вибору всіх перших елементів у 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-димного масиву: a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] всі мають різні ідентифікатори, тоді як: a[..., 0], a[..., 1], a[..., 2] всі мають однакові ідентифікатори.
mohitsharma44

@ mohitsharma44 не на моїй машині;) id()повертає однакове значення для обох. Також перевірка за допомогою __array_interface__['data']показує ту саму адресу пам'яті.
BoltzmannBrain

Я вважаю, що ми можемо використовувати в a[indexes, ...]той час, як a - це навіть одномірний масив!
акгент

1
Еліпси також корисні для нульових структур даних. Вони є єдиним способом, який я знаю, щоб записати у скалярні numpy.ndarrays, наприклад: my_scalar = np.asarray (3); my_scalar [...] = 5. Якщо ви робите my_scalar [:] = 5, ви справедливо отримаєте помилку, оскільки немає значення для 0: повторити.
Суперелектрик

1
@SuperElectric Ви також можете використовувати my_scalar.itemset (скалярне значення). Звичайно, my_scalar [...] = scalar_value коротше, але ви сказали у коментарі вище, що це єдиний спосіб, який ви знаєте. Просто даючи альтернативу.
каматлн

70

Це ще одне використання для Ellipsis, яке не має нічого спільного з фрагментами: я часто використовую його у внутрішньопотоковому спілкуванні з чергами, як позначку, яка сигналізує "Готово"; це там, це об'єкт, це синглтон, а його назва означає "відсутність", і це не перенасичений None (який можна поставити в чергу як частина нормального потоку даних). YMMV.


14
Не може бути зрозумілішим просто сказати десь: "Готово = об'єкт ()" і просто використовувати це?
Брендон Родос

12
Не обов’язково - це вимагає від вас фактично десь сказати Done = object (). Значення Sentinel не обов'язково є поганою справою - і використання в іншому випадку майже непридатних синглтонів Python як дозорних не так жахливо IMO (Еліпсис та () - це ті, які я використовував там, де Жодне не заплутало б).
Рік Коупленд

6
Щодо Done = object (), я думаю, що використовувати Ellipsis краще, особливо якщо ви використовуєте його для спілкування з чергами. Якщо ви переходите від внутрішньопотокової до внутрішньопроцесорної комунікації, id (Done) не буде однаковим в іншому процесі, і немає нічого, що відрізнятиме один об'єкт від іншого. Ідентифікатор Еліпсіса теж не буде однаковим, але принаймні тип буде однаковим - це справа сингтона.
Трістан Рейд

Питання говорить "Як ви користуєтеся еліпсісом", але я вважаю, що ви сприйняли це неправильно. Він має багато тлумачень. Але я вважаю, що правильним є: "Як застосовується Еліпсис?" тобто "Які дії я повинен зробити, щоб використати 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])
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.