Apa yang dilakukan objek Ellipsis?

540

Sementara berselancar di namespace saya melihat sebuah objek aneh yang disebut Ellipsis, tampaknya tidak menjadi atau melakukan sesuatu yang istimewa, tapi itu adalah builtin yang tersedia secara global.

Setelah pencarian saya menemukan bahwa itu digunakan dalam beberapa varian sintak slicing oleh Numpy dan Scipy ... tetapi hampir tidak ada yang lain.

Apakah objek ini ditambahkan ke bahasa khusus untuk mendukung Numpy + Scipy? Apakah Ellipsis memiliki makna generik atau penggunaan sama sekali?

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
Salim Fadhley
sumber
Lihat jawaban untuk stackoverflow.com/questions/752602/…
Patrick McElhaney
19
Saya menemukannya seperti ini: Saya masuk x=[];x.append(x);print(x), untuk melihat bagaimana ia menangani pengubahan objek siklis. Ia kembali [[...]]. Saya berpikir, "Saya ingin tahu apa yang terjadi jika saya mengetik [[...]]? Dugaan saya, itu akan membuat kesalahan sintaksis. Sebaliknya, itu mengembalikan [[Ellipsis]]. Python sangat aneh. Pencarian Google yang terjadi kemudian membawa saya ke halaman ini.
Cyoce
22
perhatikan bahwa ...repr rekursif hanyalah pengganti dan tidak ada hubungannya denganEllipsis
Eevee
16
Sebagai catatan tambahan, triple dot dalam impor berarti "impor dari dua paket ke atas".
Gila Fisikawan
1
@croq stackoverflow.com/q/32395926/2988730 . stackoverflow.com/q/1054271/2988730 . Keduanya harus menjelaskan semuanya, dengan tautan yang tepat ke dokumen dan PEP dalam jawabannya.
Gila Fisikawan

Jawaban:

559

Ini muncul dalam pertanyaan lain baru-baru ini. Saya akan menguraikan jawaban saya dari sana:

Ellipsis adalah objek yang dapat muncul dalam irisan notasi. Sebagai contoh:

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

Penafsirannya murni untuk apa pun yang mengimplementasikan __getitem__fungsi dan melihat Ellipsisobjek di sana, tetapi penggunaan utamanya (dan yang dimaksudkan) adalah di perpustakaan pihak ketiga yang numpy , yang menambahkan tipe array multidimensi. Karena ada lebih dari satu dimensi, mengiris menjadi lebih kompleks dari sekadar indeks awal dan berhenti; itu berguna untuk dapat memotong dalam berbagai dimensi juga. Misalnya, diberikan array 4x4, area kiri atas akan ditentukan oleh slice [: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]])

Memperluas ini lebih lanjut, Ellipsis digunakan di sini untuk menunjukkan placeholder untuk sisa dimensi array yang tidak ditentukan. Anggap saja menunjukkan irisan penuh [:]untuk semua dimensi di celah itu ditempatkan, jadi untuk array 3d, a[...,0]sama dengan a[:,:,0]dan untuk 4d a[:,:,:,0], sama halnya, a[0,...,0]adalah a[0,:,:,0](dengan bagaimanapun banyak titik dua di tengah membuat angka penuh dimensi dalam array).

Menariknya, dalam python3, literal Ellipsis ( ...) dapat digunakan di luar sintaks slice, sehingga Anda dapat benar-benar menulis:

>>> ...
Ellipsis

Selain berbagai jenis numerik, tidak, saya tidak berpikir itu digunakan. Sejauh yang saya ketahui, itu ditambahkan murni untuk penggunaan numpy dan tidak memiliki dukungan inti selain menyediakan objek dan sintaks yang sesuai. Objek yang ada di sana tidak memerlukan ini, tetapi dukungan "..." literal memang diperlukan.

Brian
sumber
22
itu juga digunakan dalam tipe PEP484 yang mengisyaratkan dalam file rintisan
noɥʇʎԀʎzɐɹƆ
24
Kalau-kalau ada yang penasaran: ini juga digunakan dalam typingmodul standar-perpustakaan : misalnya Callable[..., int]untuk menunjukkan callable yang mengembalikan inttanpa menentukan tanda tangan, atau Tuple[str, ...]untuk menunjukkan tupel string homogen panjang variabel.
Anakhand
6
FYI, kerangka kerja FastAPI (yang untuk python 3.6+) juga (sekarang) menggunakannya. fastapi.tiangolo.com/tutorial/query-params-str-validations
Andrew Allaire
2
@ ArtOfWarfare Anda sepenuhnya benar, dan ini berasal dari seseorang yang secara verbal mengatakan "ellipsis" alih-alih mengikuti kalimat.
PrimeRibeyeDeal
Aku menemukan ini. Tampaknya muncul ketika Anda membuat referensi-diri (referensi melingkar) dalam daftar: a = [1, 2]; a[0] = a; print(a)memberi [[...], 2]. Apakah ini hal yang sama atau penggunaan yang berbeda?
Bill
220

Dalam Python 3, Anda bisa menggunakan Ellipsis literal ...sebagai pengganti "nop" untuk kode:

def will_do_something():
    ...

Ini bukan sihir; ekspresi apa pun dapat digunakan sebagai ganti ..., misalnya:

def will_do_something():
    1

(Tidak dapat menggunakan kata "sanksi", tetapi saya dapat mengatakan bahwa penggunaan ini tidak langsung ditolak oleh Guido.)

tzot
sumber
181
Dalam setengah konvensi, saya sering melihat ...digunakan di mana orang ingin menunjukkan sesuatu yang mereka ingin isi nanti (blok kosong 'todo') dan passberarti blok yang dimaksudkan untuk tidak memiliki kode.
Gareth Latty
26
Python juga memiliki NotImplementedliteral, yang berguna ketika Anda ingin fungsi tidak lengkap Anda mengembalikan sesuatu yang bermakna (bukan Noneseperti dalam contoh Anda). (Penggunaan kata lain: Melaksanakan operasi aritmatika )
zvyn
13
@ zvyn Itu bukan literal. Itu hanya sebuah nama. Sebagai contoh NotImplemented = 'something_else'adalah python yang valid, tetapi ... = 'something_else'merupakan kesalahan sintaksis.
wim
4
@zvyn Bagaimana jika pengecualian terjadi saat mengimpor modul itu? :)
pizzapants184
7
@zvyn NotImplementedtidak dimaksudkan sebagai alternatif None. Penggunaannya agak sempit. Lihat dokumentasi di sini
hans
69

Pada Python 3.5 dan PEP484 , elipsis literal digunakan untuk menunjukkan tipe tertentu ke pemeriksa tipe statis saat menggunakan modul mengetik .

Contoh 1:

Tupel homogen yang panjangnya sewenang-wenang dapat diekspresikan menggunakan satu jenis dan elipsis, misalnya Tuple[int, ...]

Contoh 2:

Dimungkinkan untuk menyatakan tipe kembalinya callable tanpa menentukan tanda tangan panggilan dengan mengganti ellipsis literal (tiga titik) untuk daftar argumen:

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

Anda juga dapat menggunakan Ellipsis ketika menentukan output dokumen yang diharapkan :

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
Chiggs
sumber
9
Tetapi apakah ini benar-benar melibatkan objek Ellipsis? Bukankah itu hanya fitur parser / matcher doctest?
akaihola
1
@akaihola saya akan mengatakan itu, seperti yang dijelaskan di doctest.ELLIPSIS . Saya berharap bahwa sebagian besar jika tidak semua penggunaan ...sintaksis, dan bukan useobjek Ellipsis yang sebenarnya. Bukankah itu benar-benar tidak lebih dari nama yang berguna untuk konsep yang mudah beradaptasi?
nealmcb
34

Dari dokumentasi Python :

Objek ini biasa digunakan dengan mengiris (lihat Irisan ). Ini tidak mendukung operasi khusus. Tepat ada satu objek elipsis, bernama Ellipsis (nama bawaan). type(Ellipsis)()menghasilkan Ellipsis singleton.

Itu ditulis sebagai Ellipsisatau ....

Simon Lieschke
sumber
25

Meringkas apa yang dikatakan orang lain, pada Python 3, Ellipsis pada dasarnya adalah konstanta singleton lain yang serupa None, tetapi tanpa tujuan penggunaan khusus. Penggunaan yang ada meliputi:

  • Dalam sintaks irisan untuk mewakili irisan penuh dalam dimensi yang tersisa
  • Dalam tip, isyarat untuk mengindikasikan hanya sebagian dari tipe ( Callable[..., int]atauTuple[str, ...] )
  • Dalam jenis file rintisan untuk menunjukkan ada nilai default tanpa menentukannya

Kemungkinan penggunaan dapat meliputi:

  • Sebagai nilai default untuk tempat-tempat yang Nonemerupakan opsi yang valid
  • Sebagai konten untuk fungsi yang belum Anda terapkan
Matthew D. Scholefield
sumber
14

__getitem__...contoh minimal di kelas khusus

Ketika sintaks sihir ...dilewatkan ke []dalam kelas khusus, __getitem__()menerima Ellipsisobjek kelas.

Kelas kemudian dapat melakukan apa pun yang diinginkan dengan objek Singleton ini.

Contoh:

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)

Python bawaan list memilih untuk memberikan semantik suatu range, dan setiap penggunaan warasnya tentu saja juga.

Secara pribadi, saya tinggal menjauhinya di API saya, dan membuat metode terpisah yang lebih eksplisit.

Diuji dalam Python 3.5.2 dan 2.7.12.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber
jalankan ini dengan argumen -O dan kode Anda akan selalu berjalan; D
moshevi
12

Anda dapat menggunakan Ellipsis sendiri, dalam situasi pemotongan kustom seperti yang dilakukan numpy, tetapi tidak ada gunanya di kelas builtin.

Saya tidak tahu apakah itu ditambahkan khusus untuk digunakan dalam numpy, tapi saya pasti belum melihatnya digunakan di tempat lain.

Lihat juga: Bagaimana Anda menggunakan sintaks slicing ellipsis di Python?

sykora
sumber
7

Seperti disebutkan oleh @ noɥʇʎԀʎzɐɹƆ dan @ phoenix - Anda memang dapat menggunakannya dalam file rintisan. misalnya

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

Informasi lebih lanjut dan contoh cara menggunakan elipsis ini dapat ditemukan di sini https://www.python.org/dev/peps/pep-0484/#stub-files

henryJack
sumber
2

Penggunaan yang dimaksudkan seharusnya tidak hanya untuk modul pihak ke-3 ini. Itu tidak disebutkan dengan benar dalam dokumentasi Python (atau mungkin saya tidak bisa menemukannya) tetapi ellipsis ...sebenarnya digunakan dalam CPython di setidaknya satu tempat.

Ini digunakan untuk mewakili struktur data tak terbatas dalam Python. Saya menemukan notasi ini sambil bermain-main dengan daftar.

Lihat pertanyaan ini untuk info lebih lanjut.

Aseem Bansal
sumber
8
Berbagai hal. Pertanyaan ini menanyakan tentang ellipsistipe dan Ellipsisobjek bawaan. Mewakili struktur data tanpa batas dengan elips murni untuk tampilan, tidak ada hubungannya dengan ellipsisjenis atau Ellipsisobjek.
chys
3
@chys Sebenarnya, ini memang dengan cara yang kecil - __repr__string Python bertujuan untuk menjadi ekspresi Python yang valid - jika bukan karena ellipsis yang ada dalam bahasa seperti itu, representasi tidak akan menjadi ekspresi yang valid.
Gareth Latty
3
@ Lattyware Nah, memang benar desain aslinya begitu berniat. Itu juga eval(repr(a))bertujuan untuk menjadi sama dengan a. Sayangnya itu salah dari waktu ke waktu dalam praktik, bahkan untuk tipe bawaan. Mencoba ini: a=[]; a.append(a); eval(repr(a)). repr(a)adalah [[...]], ekspresi tidak valid dalam Python 2. (Dalam Python 3 itu valid, tetapi hasil eval adalah sesuatu yang berbeda, masih bertentangan dengan niat asli.)
chys
1

Ini setara.

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

...adalah konstanta yang didefinisikan di dalam built-in constants.

Elipsis

Sama dengan ellipsis literal "...". Nilai khusus yang digunakan sebagian besar bersama dengan sintaks slicing yang diperluas untuk tipe data kontainer yang ditentukan pengguna.

prosti
sumber