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


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.


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


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

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

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


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

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.


jalankan ini dengan argumen -O dan kode Anda akan selalu berjalan; D
moshevi


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


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.


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.