Що робить об’єкт Еліпсиса?


539

Під час неробного серфінгу в просторі імен я помітив дивний вигляд об'єкта, який називається Ellipsis, він, схоже, не робить чи нічого особливого, але це всесвітньо доступний вбудований модуль.

Після пошуку я виявив, що він використовується в якомусь незрозумілому варіанті синтаксису нарізки Numpy та Scipy ... але майже нічого іншого.

Чи додали цей об'єкт до мови спеціально для підтримки Numpy + Scipy? Чи має Еліпсіс якесь загальне значення або взагалі використовує?

D:\workspace\numpy>python
Python 2.4.4 (#71, Oct 18 2006, 08:34:43) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> Ellipsis
Ellipsis

Дивіться відповіді на stackoverflow.com/questions/752602 / ...
Patrick McElhaney

19
Я знайшов це так: я ввійшов x=[];x.append(x);print(x), щоб побачити, як він обробляє строфікуючі циклічні об'єкти. Це повернулося [[...]]. Я подумав: "Цікаво, що трапиться, якщо я набираю [[...]]? Думаю, що це призведе до синтаксичної помилки. Натомість повернувся [[Ellipsis]]. Python настільки дивний. Пошук Google, який виник, привів мене до цієї сторінки.
Cyoce

22
зауважте, що ...рекурсивний репр - просто заповнювач та не має жодного відношення доEllipsis
Eevee

16
Зовсім побічна примітка, потрійна крапка в імпорті означає "імпорт з двох пакетів вгору".
Божевільний фізик

1
@croq stackoverflow.com/q/32395926/2988730 . stackoverflow.com/q/1054271/2988730 . Ці два повинні пояснити все, з відповідними посиланнями на документи та PEP у відповідях.
Божевільний фізик

Відповіді:


557

Це з’явилося в іншому питанні нещодавно. Я докладу детальну відповідь :

Еліпсис - це об'єкт, який може відображатися у позначенні фрагментів. Наприклад:

myList[1:2, ..., 0]

Її інтерпретація суто залежить від того, що реалізує __getitem__функцію та бачить Ellipsisтам об’єкти, але її основне (і призначене) використання полягає в нумерованій сторонній бібліотеці, яка додає багатовимірний тип масиву. Оскільки існує більше одного виміру, нарізка стає складнішою, ніж просто індекс старту та зупинки; корисно також мати можливість нарізати в декількох вимірах. Напр., Маючи масив 4x4, верхній лівий ділянку визначатиметься зрізом [:2,:2]:

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

>>> a[:2,:2]  # top left
array([[1, 2],
       [5, 6]])

Подовжуючи це далі, Ellipsis використовується тут для позначення заповнення для решти розмірів масиву, не вказаних. Подумайте про це як про те, що вказує повний зріз [:]для всіх розмірів у проміжку, на який він розміщений, тому для 3d-масиву a[...,0]такий самий, як a[:,:,0]і для 4d a[:,:,:,0], аналогічно, так a[0,...,0]як a[0,:,:,0](хоча багато колонок посередині складають повне число розмірів у масиві).

Цікаво, що в python3 буквар Ellipsis ( ...) може бути використаний поза синтаксисом зрізу, тому ви можете фактично писати:

>>> ...
Ellipsis

Крім різних числових типів, ні, я не думаю, що він використовується. Наскільки мені відомо, він доданий виключно для нумерового використання і не має основної підтримки, крім надання об’єкта та відповідного синтаксису. Об'єкт, що перебуває там, цього не потребував, але буквальна підтримка фрагментів "..." зробила.


22
він також використовується у натяках на PEP484 у файлах заглушки
noɥʇʎԀʎzɐɹƆ

24
На випадок, якщо хтось цікавий: він також використовується в typingмодулі стандартної бібліотеки : наприклад, Callable[..., int]для вказівки дзвінка, який повертає intбез вказівки підпису, або Tuple[str, ...]для вказівки однорідного набору рядків змінної довжини.
Анаханд

6
FYI, фреймворк FastAPI (який призначений для python 3.6+) також використовує (зараз). fastapi.tiangolo.com/tutorial/query-params-str-validations
Андрій

2
@ArtOfWarfare ви абсолютно праві, і це походить від того, хто словесно каже "еліпсис", а не відставати між реченнями.
PrimeRibeyeDeal

Я це знайшов. Це , здається, з'являються , коли ви робите Автореференція (циклічна посилання) в списку: a = [1, 2]; a[0] = a; print(a)дає [[...], 2]. Це одне і те ж чи інше використання?
Білл

219

У Python 3 ви можете використовувати літерал Ellipsis ...як заповнювач "nop" для коду:

def will_do_something():
    ...

Це не магія; будь-який вираз може бути використаний замість ..., наприклад:

def will_do_something():
    1

(Не можу вживати слово "санкціонований", але можу сказати, що це використання не було відверто відверто Гвідо.)


180
На півконвенції я часто бачу ...використаний, коли люди хочуть вказати щось, що вони мають намір заповнити пізніше (порожній блок «todo») і passозначати блок, який не повинен мати код.
Гарет Летті

26
У Python також є NotImplementedбуквальне, що корисно, коли ви хочете, щоб ваша неповна функція повертала щось значуще (замість того, Noneяк у вашому прикладі). (Інша справа: реалізація арифметичних операцій )
zvyn

13
@zvyn Це не буквально. Це просто ім'я. Наприклад NotImplemented = 'something_else', дійсний python, але ... = 'something_else'є помилкою синтаксису.
Вім

4
@zvyn Що робити, якщо під час імпорту цього модуля сталася виняток? :)
pizzapants184

7
@zvyn NotImplementedне призначений бути альтернативою None. Його використання досить вузьке. Дивіться документацію тут
hans

68

Як і для Python 3.5 та PEP484 , буквальний еліпсис використовується для позначення певних типів статичним типом при використанні модуля набору тексту .

Приклад 1:

Однорідні кортежі довільної довжини можна виразити, використовуючи, наприклад, один тип та еліпсис Tuple[int, ...]

Приклад 2:

Можна оголосити тип повернення дзвінка без вказівки підпису виклику, замінивши буквальний еліпсис (три крапки) для списку аргументів:

def partial(func: Callable[..., str], *args) -> Callable[..., str]:
    # Body

46

Ви також можете використовувати програму Ellipsis, визначаючи очікуваний вихідний документ:

class MyClass(object):
    """Example of a doctest Ellipsis

    >>> thing = MyClass()
    >>> # Match <class '__main__.MyClass'> and <class '%(module).MyClass'>
    >>> type(thing)           # doctest:+ELLIPSIS
    <class '....MyClass'>
    """
    pass

9
Але чи насправді це стосується об’єкта Еліпсиса? Це не лише особливість аналізатора / матчера доктестів?
akaihola

1
@akaihola Я б сказав, що це так, як описано в doctest.ELLIPSIS . Я очікую, що більшість, якщо не всі сфери використання, ...є синтаксичними, і не useє власне об'єктом Ellipsis. Це насправді не що інше, як зручне ім’я для адаптованої концепції?
nealmcb

34

З документації Python :

Цей об'єкт зазвичай використовується для нарізки (див. Нарізки ). Він не підтримує спеціальних операцій. Існує рівно один об’єкт еліпсису під назвою Ellipsis (вбудована назва). type(Ellipsis)()виробляє одинарний еліпсис.

Він пишеться як Ellipsisабо ....


25

Підсумовуючи сказане іншими, що стосується Python 3, Ellipsis є по суті ще однією однотонною постійною, подібною None, але без конкретного призначення. До існуючих цілей використання належать:

  • У синтаксисі зрізів представити повний зріз у інших розмірах
  • Підказка типу вказує лише частину типу ( Callable[..., int]або Tuple[str, ...])
  • У файлах заглушки вкажіть, що є значення за замовчуванням, не вказуючи його

Можливі варіанти використання можуть включати:

  • Як значення за замовчуванням для місць, де Noneє дійсним параметром
  • В якості вмісту функції ви ще не реалізували

14

__getitem__мінімальний ...приклад у спеціальному класі

Коли магічний синтаксис ...переходить []у спеціальний клас, __getitem__()отримує об’єкт Ellipsisкласу.

Потім клас може робити все, що завгодно, з цим об'єктом Singleton.

Приклад:

class C(object):
    def __getitem__(self, k):
        return k

# Single argument is passed directly.
assert C()[0] == 0

# Multiple indices generate a tuple.
assert C()[0, 1] == (0, 1)

# Slice notation generates a slice object.
assert C()[1:2:3] == slice(1, 2, 3)

# Ellipsis notation generates the Ellipsis class object.
# Ellipsis is a singleton, so we can compare with `is`.
assert C()[...] is Ellipsis

# Everything mixed up.
assert C()[1, 2:3:4, ..., 6] == (1, slice(2,3,4), Ellipsis, 6)

Вбудований listклас Python вирішує надати йому семантичний діапазон, і звичайно, будь-яке розумне використання його також повинно.

Особисто я просто тримаюсь подалі від цього у своїх API, а натомість створюю окремий, більш чіткий метод.

Випробувано в Python 3.5.2 та 2.7.12.


запустіть це з аргументом -O, і ваш код завжди буде працювати; D
moshevi

12

Ви можете використовувати Ellipsis самостійно в таких ситуаціях, як нумез, але це не використовується в будь-якому вбудованому класі.

Я не знаю, чи був він доданий спеціально для використання в нуме, але я, звичайно, не бачив його в іншому місці.

Дивіться також: Як ви використовуєте синтаксис нарізки еліпсису в Python?


7

Як згадували @ noɥʇʎԀʎzɐɹƆ та @phoenix - Ви дійсно можете використовувати його у файлах stub. напр

class Foo:
    bar: Any = ...
    def __init__(self, name: str=...) -> None: ...

Більше інформації та приклади використання цього еліпсису можна знайти тут https://www.python.org/dev/peps/pep-0484/#stub-files


2

Її використання не повинно бути тільки для цих сторонніх модулів. Це не згадується належним чином в документації на Python (або, можливо, я просто не міг цього знайти), але еліпсис ...насправді використовується в CPython принаймні в одному місці.

Він використовується для представлення нескінченних структур даних у Python. Я натрапив на це позначення, граючи зі списками.

Дивіться це питання для отримання додаткової інформації.


8
Різні речі. Це питання задається про ellipsisвбудований тип та Ellipsisоб'єкт. Представлення нескінченних структур даних з еліпсами суто для відображення, не маючи нічого спільного з ellipsisтипом або Ellipsisоб'єктом.
chys

3
@chys Насправді це робиться невеликим чином - __repr__рядки Python мають на меті бути дійсними виразами Python - якби не еліпсис, який існує в мові, як це є, представлення не було б допустимим виразом.
Гарет Летті

3
@Lattyware Ну, це правда, оригінальний дизайн так має намір. Він також має на eval(repr(a))меті бути рівним a. На жаль, це періодично помиляється на практиці, навіть для вбудованих типів. Спробуйте це: a=[]; a.append(a); eval(repr(a)). repr(a)є [[...]]недійсним виразом у Python 2. (У Python 3 це дійсно, але результат eval дещо інший, все-таки суперечить первинному наміру.)
chys

1

Це рівнозначно.

l=[..., 1,2,3]
l=[Ellipsis, 1,2,3]

...- це константа, визначена всередині built-in constants.

Еліпсис

Те саме, що буквально "...". Особливе значення використовується в основному в поєднанні з розширеним синтаксисом нарізки для визначених користувачем типів контейнерів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.