Dalam Python, ada dua jenis yang sama - daftar (daftar) dan tuple (tuple). Perbedaan paling terkenal antara keduanya adalah bahwa tupel tidak dapat diubah.
Anda tidak dapat mengubah objek dalam tuple:
>>> a = (1,2,3) >>> a[0] = 10 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'tuple' object does not support item assignment
Tapi Anda bisa memodifikasi objek yang bisa berubah di dalam tuple:
>>> b = (1,[1,2,3],3) >>> b[1] [1, 2, 3] >>> b[1].append(4) >>> b (1, [1, 2, 3, 4], 3)
Di dalam CPython (penerjemah standar), daftar dan tuple diimplementasikan sebagai selembar pointer (tautan) ke objek Python, mis. secara fisik mereka tidak menyimpan benda bersebelahan. Saat Anda menghapus objek dari daftar, referensi ke objek ini dihapus. Jika orang lain mengacu pada objek, itu akan terus berada dalam memori.
Tuples
Terlepas dari kenyataan bahwa tupel jauh lebih jarang terjadi dalam kode dan tidak begitu populer, ini adalah tipe yang sangat mendasar yang digunakan oleh Python untuk keperluan internal.
Anda mungkin tidak melihat, tetapi Anda menggunakan tuple ketika:
- bekerja dengan argumen atau parameter (disimpan sebagai tupel)
- mengembalikan dua atau lebih variabel dari suatu fungsi
- iterate kunci nilai dalam kamus
- gunakan pemformatan string
Biasanya, skrip paling sederhana menggunakan ribuan tupel:
>>> import gc >>> def type_stats(type_obj): ... count = 0 ... for obj in gc.get_objects(): ... if type(obj) == type_obj: ... count += 1 ... return count ... >>> type_stats(tuple) 3136 >>> type_stats(list) 659 >>> import pandas >>> type_stats(tuple) 6953 >>> type_stats(list) 2455
Daftar kosong vs tuple kosong
Sebuah tuple kosong berfungsi seperti singleton, mis. selalu ada hanya satu tuple kosong di memori skrip Python yang sedang berjalan. Semua tupel kosong hanya merujuk ke objek yang sama, ini dimungkinkan karena tupel tidak berubah. Pendekatan ini menghemat banyak memori dan mempercepat proses bekerja dengan tuple kosong.
>>> a = () >>> b = () >>> a is b True >>> id(a) 4409020488 >>> id(b) 4409020488 >>>
Tetapi ini tidak berfungsi dengan daftar, karena mereka dapat diubah:
>>> a = [] >>> b = [] >>> a is b False >>> id(a) 4465566920 >>> id(b) 4465370632
Mengoptimalkan alokasi memori untuk tupel
Untuk mengurangi fragmentasi memori dan mempercepat pembuatan tupel, Python menggunakan kembali tupel lama yang telah dihapus. Jika sebuah tuple terdiri dari kurang dari 20 elemen dan tidak lagi digunakan, maka alih-alih menghapusnya, Python menempatkannya dalam daftar khusus, yang menyimpan tuple gratis untuk digunakan kembali.
Daftar ini dibagi menjadi 20 kelompok, di mana masing-masing kelompok adalah daftar tupel ukuran n, di mana n adalah 0 hingga 20. Setiap kelompok dapat menyimpan hingga 2.000 tupel gratis. Grup pertama menyimpan hanya satu elemen dan merupakan daftar satu tuple kosong.
>>> a = (1,2,3) >>> id(a) 4427578104 >>> del a >>> b = (1,2,4) >>> id(b) 4427578104
Pada contoh di atas, kita dapat melihat bahwa a dan b memiliki alamat yang sama dalam memori. Ini karena kami mengambil tuple gratis dengan ukuran yang sama.
Mengoptimalkan alokasi memori untuk daftar
Karena daftar dapat berubah, optimasi yang sama seperti dalam kasus tupel tidak dapat lagi diputar. Meskipun demikian, daftar menggunakan pengoptimalan serupa yang ditujukan pada daftar kosong. Jika daftar kosong dihapus, maka itu juga dapat digunakan kembali di masa depan.
>>> a = [] >>> id(a) 4465566792 >>> del a >>> b = [] >>> id(b) 4465566792
Ubah Ukuran Daftar
Untuk menghindari overhead daftar perubahan ukuran terus-menerus, Python tidak mengubah ukurannya setiap kali diperlukan. Alih-alih, setiap daftar memiliki satu set sel tambahan yang disembunyikan bagi pengguna, tetapi nantinya dapat digunakan untuk elemen baru. Segera setelah sel tersembunyi berakhir, Python menambahkan ruang ekstra untuk elemen baru. Dan dia melakukannya dengan margin yang baik, jumlah sel tersembunyi dipilih berdasarkan ukuran daftar saat ini - semakin besar, semakin banyak slot tersembunyi tambahan untuk elemen baru.
Optimalisasi ini sangat membantu ketika Anda mencoba menambahkan banyak elemen dalam satu lingkaran.
Pola pertumbuhan ukuran daftar terlihat seperti ini: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
Misalnya, jika Anda ingin menambahkan elemen baru ke daftar dengan 8 elemen, maka tidak akan ada sel bebas di dalamnya dan Python akan segera memperluas ukurannya menjadi 16 sel, di mana 9 di antaranya akan ditempati dan terlihat oleh pengguna.
Rumus ukuran Python:
>>> def get_new_size(n_items): ... new_size = n_items + (n_items // 2 ** 3) ... if n_items < 9: ... new_size += 3 ... else: ... new_size += 6 ... ... return new_size ... >>> get_new_size(9) 16
Kecepatan
Jika kita membandingkan kedua jenis ini dalam kecepatan, maka rata-rata di rumah sakit, tupel sedikit lebih cepat daripada daftar. Raymond Hettinger memiliki penjelasan yang bagus untuk perbedaan kecepatan pada
stackoverflow .
PS: Saya penulis artikel ini, kamu bisa bertanya.