Apa artinya jika objek Python "subscriptable" atau tidak?

372

Jenis objek apa yang termasuk dalam domain "subscriptable"?

Alistair
sumber

Jawaban:

357

Ini pada dasarnya berarti bahwa objek mengimplementasikan __getitem__()metode. Dengan kata lain, ini menggambarkan objek yang merupakan "wadah", yang berarti mereka berisi objek lain. Ini termasuk string, daftar, tupel, dan kamus.

mipadi
sumber
2
Seberapa andal akan: hasattr(SomeClassWithoutGetItem, '__getitem__')menentukan apakah suatu barang dapat disubkripsikan?
jmunsch
2
The [... ]mengindeks sintaks disebut subscript , karena itu setara dengan notasi matematika yang menggunakan subscript yang sebenarnya; misalnya a[1]Python untuk apa yang akan ditulis oleh matematikawan sebagai a₁ . Jadi "subscriptable" berarti "bisa menjadi subscript". Yang, dalam istilah Python, berarti harus diterapkan __getitem__(), karena a[1]hanya gula sintaksis untuk a.__getitem__(1).
Mark Reed
Panggilan itu hasattrseharusnya bekerja dengan baik, tetapi itu bukan cara Pythonic untuk melakukan sesuatu; Latihan Python mendorong Bebek Mengetik . Artinya, jika Anda berencana untuk mengambil item dari objek Anda menggunakan subskrip, silakan dan lakukan; jika Anda berpikir itu mungkin tidak berhasil karena objek tidak dapat disubkripsikan, bungkus dalam tryblok dengan except TypeError.
Mark Reed
77

Dari atas kepala saya, berikut ini adalah satu-satunya built-in yang dapat disubkripsikan:

string:  "foobar"[3] == "b"
tuple:   (1,2,3,4)[3] == 4
list:    [1,2,3,4][3] == 4
dict:    {"a":1, "b":2, "c":3}["c"] == 3

Tetapi jawaban mipadi benar - setiap kelas yang mengimplementasikannya __getitem__dapat disubkripsikan

Dan
sumber
17

Objek skrip adalah objek yang mencatat operasi yang dilakukan untuk itu dan dapat menyimpannya sebagai "skrip" yang dapat diputar ulang.

Misalnya, lihat: Kerangka Kerja Skrip Aplikasi

Sekarang, jika Alistair tidak tahu apa yang dia tanyakan dan benar-benar berarti objek "dapat disandikan" (seperti yang diedit oleh orang lain), maka (seperti yang dijawab mipadi) ini adalah yang benar:

Objek subscriptable adalah objek apa pun yang mengimplementasikan __getitem__metode khusus (think list, kamus).

tzot
sumber
2
Perhatikan bahwa saya membalas pertanyaan awal tentang objek "yang dapat skrip", bukan "dapat disubkripsikan" seperti yang diedit oleh orang lain, bukan Alistair. Saya benar-benar ingin Alistair berkomentar.
tzot
Ah, lencana baru untuk koleksi saya! :) Hanya bercanda, jelas. Satu-satunya hal yang membenarkan pengeditan pertanyaan adalah Alistair memilih jawaban; Saya masih tidak yakin apakah Alistair yakin tentang memilih.
tzot
17

Arti subskrip dalam komputasi adalah: "simbol (secara tertulis ditulis sebagai subskrip tetapi dalam praktiknya biasanya tidak) digunakan dalam suatu program, sendiri atau dengan yang lain, untuk menentukan salah satu elemen dari array."

Sekarang, dalam contoh sederhana yang diberikan oleh @ user2194711 kita dapat melihat bahwa elemen appending tidak dapat menjadi bagian dari daftar karena dua alasan: -

1) Kami tidak benar-benar memanggil metode append; karena itu perlu ()menyebutnya.

2) Kesalahan mengindikasikan bahwa fungsi atau metode tidak dapat disubkripsikan; berarti mereka tidak dapat diindeks seperti daftar atau urutan.

Sekarang lihat ini: -

>>> var = "myString"
>>> def foo(): return 0
... 
>>> var[3]
't'
>>> foo[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'function' object is not subscriptable

Itu berarti tidak ada subskrip atau mengatakan elemen dalam functionseperti mereka terjadi secara berurutan; dan kami tidak dapat mengaksesnya seperti yang kami lakukan, dengan bantuan [].

Juga; seperti yang dikatakan mipadi dalam jawabannya; Ini pada dasarnya berarti bahwa objek mengimplementasikan __getitem__()metode. (jika dapat disubkripsikan). Jadi kesalahan yang dihasilkan:

arr.append["HI"]

Objek TypeError: objek 'builtin_function_or_method' tidak dapat disubkripsikan

Vicrobot
sumber
7

Saya punya masalah yang sama. saya tengah mengerjakan

arr = []
arr.append["HI"]

Jadi menggunakan [menyebabkan kesalahan. Harusarr.append("HI")

pengguna2194711
sumber
3

Sebagai jawaban wajar untuk jawaban sebelumnya di sini, sangat sering ini adalah tanda bahwa Anda berpikir Anda memiliki daftar (atau dict, atau objek subscriptable lainnya) ketika Anda tidak.

Misalnya, katakanlah Anda memiliki fungsi yang harus mengembalikan daftar;

def gimme_things():
    if something_happens():
        return ['all', 'the', 'things']

Sekarang ketika Anda memanggil fungsi itu, dan something_happens()untuk beberapa alasan tidak mengembalikan Truenilai, apa yang terjadi? The ifgagal, dan sehingga Anda jatuh; gimme_thingstidak secara eksplisit returnapa pun - jadi pada kenyataannya, itu akan secara implisit return None. Maka kode ini:

things = gimme_things()
print("My first thing is {0}".format(things[0]))

akan gagal dengan " NoneTypeobjek tidak subscriptable" karena, baik, thingsadalah Nonedan jadi Anda coba lakukan None[0]yang tidak masuk akal karena ... apa pesan kesalahan mengatakan.

Ada dua cara untuk memperbaiki bug ini dalam kode Anda - yang pertama adalah untuk menghindari kesalahan dengan memeriksa yang thingssebenarnya valid sebelum mencoba menggunakannya;

things = gimme_things()
if things:
    print("My first thing is {0}".format(things[0]))
else:
    print("No things")  # or raise an error, or do nothing, or ...

atau dengan cara yang sama menjebak TypeErrorpengecualian;

things = gimme_things()
try:
    print("My first thing is {0}".format(things[0]))
except TypeError:
    print("No things")  # or raise an error, or do nothing, or ...

Lain adalah mendesain ulang gimme_thingssehingga Anda memastikan itu selalu mengembalikan daftar. Dalam hal ini, itu mungkin desain yang lebih sederhana karena itu berarti jika ada banyak tempat di mana Anda memiliki bug yang sama, mereka dapat dibuat sederhana dan idiomatis.

def gimme_things():
    if something_happens():
        return ['all', 'the', 'things']
    else:  # make sure we always return a list, no matter what!
        logging.info("Something didn't happen; return empty list")
        return []

Tentu saja, apa yang Anda masukkan ke else:cabang tergantung pada use case Anda. Mungkin Anda harus mengajukan pengecualian ketika something_happens()gagal, agar lebih jelas dan eksplisit di mana ada sesuatu yang salah? Menambahkan pengecualian ke kode Anda sendiri adalah cara penting untuk membuat diri Anda tahu persis apa yang terjadi ketika sesuatu gagal!

(Perhatikan juga bagaimana perbaikan terakhir ini masih belum sepenuhnya memperbaiki bug - itu mencegah Anda dari mencoba untuk berlangganan, Nonetetapi things[0]masih merupakan IndexErrorkapan thingsdaftar kosong. Jika Anda memiliki tryAnda dapat melakukannya except (TypeError, IndexError)untuk menjebaknya juga.)

tripleee
sumber