Dalam Python (2 dan 3). Setiap kali kita menggunakan daftar slicing, ia mengembalikan objek baru, misalnya:
l1 = [1,2,3,4]
print(id(l1))
l2 = l1[:]
print(id(l2))
Keluaran
>>> 140344378384464
>>> 140344378387272
Jika hal yang sama diulangi dengan tuple, objek yang sama dikembalikan, misalnya:
t1 = (1,2,3,4)
t2 = t1[:]
print(id(t1))
print(id(t2))
Keluaran
>>> 140344379214896
>>> 140344379214896
Akan lebih bagus jika seseorang dapat menjelaskan mengapa ini terjadi, sepanjang pengalaman Python saya, saya mendapat kesan slice kosong mengembalikan objek baru.
Pemahaman saya adalah bahwa ia mengembalikan objek yang sama karena tupel tidak berubah dan tidak ada gunanya membuat salinan baru. Tetapi sekali lagi, itu tidak disebutkan dalam dokumen di mana pun.
l2 = tuple(iter(l1))
bypass optimasiPyTuple_GetSlice
didokumentasikan secara tidak akurat setelah melihat pertanyaan Anda. Documents kini telah diperbaiki (ini adalah bpo issue38557 ).Jawaban:
Implementasi bebas untuk mengembalikan instance identik untuk tipe yang tidak dapat diubah (dalam CPython, Anda terkadang dapat melihat optimisasi serupa untuk string dan integer). Karena objek tidak dapat diubah, tidak ada dalam kode pengguna yang perlu peduli apakah itu menyimpan instance unik atau hanya referensi lain ke instance yang ada.
Anda dapat menemukan hubungan arus pendek dalam kode C di sini .
Ini adalah detail implementasi, perhatikan bahwa pypy tidak melakukan hal yang sama.
sumber
a->ob_item
seperti(*a).ob_item
, yaitu mendapat anggota dipanggilob_item
dariPyTupleObject
yang menunjuk ke, dan + ilow kemudian maju ke awal irisan.Ini detail implementasi. Karena daftar bisa berubah,
l1[:]
harus membuat salinan, karena Anda tidak akan mengharapkan perubahanl2
mempengaruhil1
.Karena tuple tidak dapat diubah , tidak ada yang dapat Anda lakukan untuk
t2
memengaruhit1
dengan cara apa pun yang terlihat, sehingga kompiler bebas (tetapi tidak diharuskan ) untuk menggunakan objek yang sama untukt1
dant1[:]
.sumber
Dalam Python 3. *
my_list[:]
adalah gula sintaksis untuk ditype(my_list).__getitem__(mylist, slice_object)
mana:slice_object
adalah objek irisan yang dibangun darimy_list
atribut (panjang) dan ekspresi[:]
. Objek yang berperilaku seperti ini disebut subscriptable dalam model data Python lihat di sini . Untuk daftar dan tupel__getitem__
adalah metode bawaan.Dalam CPython, dan untuk daftar dan tupel,
__getitem__
ditafsirkan oleh operasi bytecodeBINARY_SUBSCR
yang diimplementasikan untuk tupel di sini dan untuk daftar di sini .Dalam hal tuple, berjalan melalui kode Anda akan melihat bahwa dalam blok kode ini ,
static PyObject* tuplesubscript(PyTupleObject* self, PyObject* item)
akan mengembalikan referensi ke yang samaPyTupleObject
yang didapatnya sebagai argumen input, jika item bertipePySlice
dan irisan mengevaluasi ke seluruh tuple.Sekarang Anda memeriksa kode
static PyObject * list_subscript(PyListObject* self, PyObject* item)
dan melihat sendiri bahwa apa pun slice, objek daftar baru selalu dikembalikan.sumber
start:stop
irisan pada tipe bawaan, termasuktup[:]
, tidak melaluiBINARY_SUBSCR
. Pengecilan yang diperpanjangstart:stop:step
tidak melalui berlangganan.Tidak yakin tentang ini tetapi tampaknya Python memberi Anda pointer baru ke objek yang sama untuk menghindari penyalinan karena tupel identik (dan karena objek adalah tupel, itu tidak berubah).
sumber