Bagaimana Anda menggunakan sintaks iris ellipsis dengan Python?

Jawaban:

102

Ellipsis, atau ...bukan fitur tersembunyi, itu hanya sebuah konstanta. Ini sangat berbeda dengan, katakanlah, javascript ES6 di mana itu adalah bagian dari sintaks bahasa. Tidak ada konstruktor kelas atau bahasa Python yang memanfaatkannya.

Jadi sintaks untuk itu sepenuhnya tergantung pada Anda, atau orang lain, memiliki kode tertulis untuk memahaminya.

Numpy menggunakannya, sebagaimana dinyatakan dalam dokumentasi . Beberapa contoh di sini .

Di kelas Anda sendiri, Anda akan menggunakannya seperti ini:

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

Tentu saja, ada dokumentasi python , dan referensi bahasa . Tapi itu tidak terlalu membantu.

nosklo
sumber
6
terlihat cukup rusak karena cara "tepat" untuk mengatakan semua item adalah >>> x [:] >>> x [:, 1: 2]
Ronny
30
@Ronny: Intinya adalah untuk menunjukkan beberapa penggunaan Ellipsis secara khusus.
nosklo
7
Tautan tampaknya rusak.
SwiftsNamesake
231

Ellipsis digunakan secara numpy untuk mengiris struktur data dimensi tinggi.

Ini dirancang untuk maksud pada titik ini, masukkan sebanyak mungkin irisan penuh ( :) untuk memperluas irisan multi-dimensi ke semua dimensi .

Contoh :

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

Sekarang, Anda memiliki matriks 4 dimensi dengan urutan 2x2x2x2. Untuk memilih semua elemen pertama dalam dimensi ke-4, Anda dapat menggunakan notasi elipsis

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

yang setara dengan

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

Dalam implementasi Anda sendiri, Anda bebas untuk mengabaikan kontrak yang disebutkan di atas dan menggunakannya untuk apa pun yang Anda inginkan.

Torsten Marek
sumber
Mungkin saya salah tetapi bukankah itu a[:,:,:,0]akan mengembalikan salinan dan a[...,0]akan mengembalikan "tampilan" dan bukan salinan? Saya mencoba menjalankan id()terhadap kedua versi dan untuk array 3-dim: a[:,:,:, 0], a[:,:,:, 1], a[:,:,:, 2] semua memiliki id yang berbeda sedangkan: a[..., 0], a[..., 1], a[..., 2] semua memiliki id yang sama.
mohitsharma44
@ mohitsharma44 bukan pada mesin saya;) id()mengembalikan nilai yang sama untuk keduanya. Juga memeriksa dengan __array_interface__['data']menunjukkan alamat memori yang sama.
BoltzmannBrain
Saya menemukan kita dapat menggunakan a[indexes, ...]sementara a adalah array 1-dimensi bahkan!
Acgtyrant
1
Elips juga berguna untuk struktur data nol dimensi. Mereka adalah satu-satunya cara saya tahu untuk menulis ke skalar numpy.ndarrays, misalnya: my_scalar = np.asarray (3); my_scalar [...] = 5. Jika Anda melakukan my_scalar [:] = 5, Anda akan mendapatkan kesalahan, karena tidak ada dimensi 0 untuk: untuk diulangi.
SuperElectric
1
@SuperElectric Anda juga dapat menggunakan my_scalar.itemset (scalarvalue). Tentu saja, my_scalar [...] = scalar_value lebih pendek, tetapi Anda mengatakan dalam komentar di atas, bahwa itu adalah satu-satunya cara yang Anda ketahui. Hanya memberi alternatif.
kamathln
70

Ini adalah kegunaan lain untuk Ellipsis, yang tidak ada hubungannya dengan irisan: Saya sering menggunakannya dalam komunikasi intra-thread dengan antrian, sebagai tanda yang menandakan "Selesai"; itu ada di sana, itu sebuah objek, itu adalah singleton, dan namanya berarti "kurangnya", dan itu bukan None (yang bisa dimasukkan ke dalam antrian sebagai bagian dari aliran data normal). YMMV.

tzot
sumber
14
Mungkinkah lebih jelas mengatakan: "Selesai = objek ()" di suatu tempat dan gunakan saja?
Brandon Rhodes
12
Belum tentu - itu mengharuskan Anda untuk benar-benar mengatakan Selesai = objek () di suatu tempat. Nilai sentinel tidak selalu merupakan hal yang buruk - dan menggunakan singleton Python yang hampir tidak berguna sebagai sentinel tidak begitu mengerikan IMO (Ellipsis dan () adalah yang saya gunakan di mana tidak ada yang membingungkan).
Rick Copeland
6
Mengenai Selesai = objek (), saya pikir menggunakan Ellipsis lebih baik, terutama jika Anda menggunakannya untuk komunikasi dengan antrian. Jika Anda beralih dari komunikasi intra-thread ke komunikasi intra-proses, id (Selesai) tidak akan sama dalam proses lainnya, dan tidak ada yang membedakan satu objek dari yang lain. Id Ellipsis juga tidak akan sama, tetapi setidaknya tipenya akan sama - ini adalah poin singleton.
Tristan Reid
Pertanyaannya mengatakan "Bagaimana Anda menggunakan ellipsis" tapi saya yakin Anda mengambil cara yang salah. Ini memiliki banyak interpretasi. Tapi saya pikir yang benar adalah: "Bagaimana Ellipsis digunakan?" yaitu "Langkah apa yang harus saya ambil untuk memanfaatkan Ellipsis dalam kode saya sendiri."
Lyndon White
6

Seperti yang dinyatakan dalam jawaban lain, ini dapat digunakan untuk membuat irisan. Berguna ketika Anda tidak ingin menulis banyak notasi irisan penuh (: ), atau ketika Anda tidak yakin tentang apa dimensi array yang sedang dimanipulasi.

Apa yang saya anggap penting untuk disorot, dan yang hilang pada jawaban lain, adalah bahwa itu dapat digunakan bahkan ketika tidak ada lagi dimensi yang harus diisi.

Contoh:

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

Ini akan menghasilkan kesalahan:

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

Ini akan berhasil:

a[...,0,:]
array([0, 1])
Mauricio Perez
sumber