Daftar Python vs. Array - kapan digunakan?

375

Jika Anda membuat larik 1d, Anda bisa menerapkannya sebagai Daftar, atau gunakan modul 'larik' di perpustakaan standar. Saya selalu menggunakan Daftar untuk array 1d.

Apa alasan atau keadaan di mana saya ingin menggunakan modul array?

Apakah ini untuk kinerja dan optimalisasi memori, atau apakah saya kehilangan sesuatu yang jelas?

Corey Goldberg
sumber

Jawaban:

438

Pada dasarnya, daftar Python sangat fleksibel dan dapat menyimpan data yang sepenuhnya heterogen, sewenang-wenang, dan mereka dapat ditambahkan dengan sangat efisien, dalam waktu konstan yang diamortisasi . Jika Anda perlu mengecilkan dan menumbuhkan daftar Anda secara efisien dan tanpa kerumitan, mereka adalah cara untuk melakukannya. Tapi mereka menggunakan lebih banyak ruang daripada C array .

The array.arrayjenis, di sisi lain, hanya bungkus tipis pada C array. Itu hanya dapat menyimpan data homogen, semua dari jenis yang sama, dan hanya menggunakan sizeof(one object) * lengthbyte memori. Sebagian besar, Anda harus menggunakannya ketika Anda perlu mengekspos array C ke ekstensi atau panggilan sistem (misalnya, ioctlatau fctnl).

array.arrayjuga merupakan cara yang masuk akal untuk mewakili string yang dapat berubah dalam Python 2.x ( array('B', bytes)). Namun, Python 2.6+ dan 3.x menawarkan byte string yang dapat diubah sebagai bytearray.

Namun, jika Anda ingin melakukan matematika pada array data numerik yang homogen, maka Anda jauh lebih baik menggunakan NumPy, yang dapat secara otomatis mengubah operasi pada array multi-dimensi yang kompleks.

Untuk membuat cerita panjang pendek : array.arrayberguna ketika Anda membutuhkan array data C homogen untuk alasan selain melakukan matematika .

Dan Lenski
sumber
9
Apakah numpy.ndarray memiliki jejak memori yang sama dengan array.array?
Gordon Bean
6
@ Gordon, itu harus sangat mirip dalam kasus array, berdekatan besar: mereka berdua akan memerlukan sizeof(element)× (jumlah elemen) byte, ditambah header kecil yang tetap untuk overhead. Namun, ndarray memiliki beberapa opsi lanjutan untuk berurusan dengan array yang tidak jelas dan jarang, dan saya pikir beberapa strategi pluggable untuk mengalokasikan memori untuk array besar ... beberapa fitur canggih ini akan membuat pengguna lebih sedikit memori, sementara yang lain akan meningkatkan kinerja dengan menggunakan lebih banyak Penyimpanan.
Dan Lenski
Juga berguna ketika memori adalah masalah seperti ketika memprogram pengontrol mikro dengan micropython
janscas
Seseorang dapat mencari elemen ke-10 dari array dalam waktu yang konstan, sedangkan dalam daftar tertaut, dibutuhkan urutan 'n' dalam kasus terburuk. Apa waktu pencarian elemen ke-10 dalam daftar python?
Nithish Inpursuit Ofhappiness
7
@NithishInpursuitOfhappiness, daftar Python bukan daftar yang ditautkan. Ini direpresentasikan secara internal sebagai array dan memiliki karakteristik kompleksitas waktu yang sama dengan Java's ArrayList. Dengan demikian, mendapatkan dan mengatur elemen ke-i dari daftar Python membutuhkan waktu yang konstan . Menambahkan elemen ke daftar Python membutuhkan waktu konstan diamortisasi karena ukuran array dua kali lipat ketika kehabisan ruang. Memasukkan elemen ke dalam atau menghapus dari tengah daftar Python membutuhkan O (n) waktu karena elemen perlu digeser. Untuk referensi, lihat: wiki.python.org/moin/TimeComplexity
geofflee
66

Untuk hampir semua kasus, daftar normal adalah pilihan yang tepat. Modul array lebih seperti pembungkus tipis di atas array C, yang memberi Anda jenis wadah yang sangat diketik (lihat dokumen ), dengan akses ke lebih banyak jenis mirip-C seperti bertanda / tidak bertanda pendek atau ganda, yang bukan bagian dari build. dalam tipe. Saya akan mengatakan menggunakan modul array hanya jika Anda benar-benar membutuhkannya, dalam semua kasus tetap dengan daftar.

André
sumber
3
Mungkin, tidak pernah menggunakannya benar-benar, tetapi akan menarik untuk menjalankan beberapa tolok ukur mikro.
André
13
Sebenarnya, saya melakukan tes cepat - saya menghitung waktu daftar dengan 100 juta entri dan tes yang sama dengan array yang sesuai, dan daftar itu sebenarnya sekitar 10% lebih cepat.
Moe
38
Daftar lebih cepat, karena operasi pada array "mentah" data perlu terus membuat dan menghancurkan objek python saat membaca dari atau menulis ke array.
tzot
7
@Moe, seperti yang saya tunjukkan dalam jawaban saya di atas, Python built-in arrayyang tidak dimaksudkan untuk melakukan matematika . Jika Anda mencoba NumPy ndarrayuntuk menjumlahkan array 10 ^ 8 angka, itu akan sepenuhnya meledak list. @tzot memiliki ide yang tepat tentang mengapa built-in arraylambat untuk matematika.
Dan Lenski
2
Saya baru saja mengujinya, numpy adalah 86,6x lebih cepat pada mesin saya.
Markus
53

Modul array adalah salah satu dari hal-hal yang Anda mungkin tidak perlu jika Anda tidak tahu mengapa Anda akan menggunakannya (dan perhatikan bahwa saya tidak mencoba mengatakan itu dengan cara merendahkan!) . Sebagian besar waktu, modul array digunakan untuk berinteraksi dengan kode C. Untuk memberikan jawaban yang lebih langsung untuk pertanyaan Anda tentang kinerja:

Array lebih efisien daripada daftar untuk beberapa kegunaan. Jika Anda perlu mengalokasikan array yang Anda TAHU tidak akan berubah, maka array bisa lebih cepat dan menggunakan lebih sedikit memori. GvR memiliki anekdot optimisasi di mana modul array keluar sebagai pemenang (sudah lama dibaca, tetapi tidak sia-sia).

Di sisi lain, bagian dari alasan mengapa daftar memakan lebih banyak memori daripada array adalah karena python akan mengalokasikan beberapa elemen tambahan ketika semua elemen yang dialokasikan digunakan. Ini berarti menambahkan item ke daftar lebih cepat. Jadi, jika Anda berencana menambahkan item, daftar adalah cara untuk pergi.

TL; DR Saya hanya akan menggunakan array jika Anda memiliki kebutuhan optimasi yang luar biasa atau Anda perlu berinteraksi dengan kode C (dan tidak dapat menggunakan pyrex ).

Jason Baker
sumber
1
+1 untuk contoh konkret dan menyebutkan manfaat kecepatan. Jawaban teratas membuat saya bertanya-tanya, "Apakah ada pertukaran waktu-ingatan?" dan "Apakah ada gunanya untuk ini yang bukan kasus memori rendah yang sangat esoteris?"
leewz
@ewewz tepatnya, ini harus dianggap sebagai jawaban.
Gauri Shankar Badola
21

Ini adalah trade off!

kelebihan masing-masing:

daftar

  • fleksibel
  • bisa heterogen

array (ex: numpy array)

  • array nilai seragam
  • homogen
  • kompak (dalam ukuran)
  • efisien (fungsionalitas dan kecepatan)
  • mudah
Mohammad Mahdi KouchakYazdi
sumber
2
pertanyaannya adalah merujuk ke modul array dalam python; bukan array numpy. Mereka tidak memiliki banyak kelebihan kecuali efisiensi ukuran. Mereka tidak lebih cepat.
NONONONONO
14

Pemahaman saya adalah bahwa array disimpan lebih efisien (yaitu sebagai blok memori yang berdekatan vs pointer ke objek Python), tetapi saya tidak mengetahui adanya manfaat kinerja. Selain itu, dengan array Anda harus menyimpan primitif dari jenis yang sama, sedangkan daftar dapat menyimpan apa pun.

Ben Hoffstein
sumber
8

Array pustaka standar berguna untuk biner I / O, seperti menerjemahkan daftar ints ke string untuk menulis, katakanlah, file gelombang. Yang mengatakan, seperti banyak yang telah dicatat, jika Anda akan melakukan pekerjaan nyata maka Anda harus mempertimbangkan menggunakan NumPy.

Giltay
sumber
6

Jika Anda akan menggunakan array, pertimbangkan paket numpy atau scipy, yang memberi Anda array dengan lebih banyak fleksibilitas.

Alex Coventry
sumber
5

Array hanya dapat digunakan untuk tipe tertentu, sedangkan daftar dapat digunakan untuk objek apa pun.

Array juga hanya dapat data dari satu jenis, sedangkan daftar dapat memiliki entri dari berbagai jenis objek.

Array juga lebih efisien untuk beberapa perhitungan numerik.

Hortitude
sumber
4
Array python bawaan tidak efisien dalam kinerja, hanya memori.
tzot
ADA contoh di mana array lebih efisien dalam hal pemrosesan. Lihat posting saya di bawah ini: stackoverflow.com/questions/176011/…
Jason Baker
0

Perbedaan penting antara array numpy dan daftar adalah bahwa irisan array adalah tampilan pada array asli. Ini berarti bahwa data tidak disalin, dan setiap modifikasi tampilan akan tercermin dalam larik sumber.

vivek
sumber
0

Jawaban ini akan merangkum hampir semua pertanyaan tentang kapan harus menggunakan Daftar dan Array:

  1. Perbedaan utama antara kedua tipe data ini adalah operasi yang dapat Anda lakukan pada mereka. Misalnya, Anda dapat membagi array dengan 3 dan itu akan membagi setiap elemen array dengan 3. Sama tidak dapat dilakukan dengan daftar.

  2. Daftar ini adalah bagian dari sintaks python sehingga tidak perlu dideklarasikan sedangkan Anda harus mendeklarasikan array sebelum menggunakannya.

  3. Anda bisa menyimpan nilai tipe data yang berbeda dalam daftar (heterogen), sedangkan di Array Anda hanya bisa menyimpan nilai hanya tipe data yang sama (homogen).

  4. Array kaya akan fungsi dan cepat, ini banyak digunakan untuk operasi aritmatika dan untuk menyimpan sejumlah besar data - dibandingkan dengan daftar.

  5. Array mengambil lebih sedikit memori dibandingkan dengan daftar.

Dipen Gajjar
sumber
0

Berkenaan dengan kinerja, berikut adalah beberapa angka yang membandingkan daftar python, array dan array numpy (semua dengan Python 3.7 pada 2017 Macbook Pro). Hasil akhirnya adalah bahwa daftar python tercepat untuk operasi ini.

# Python list with append()
np.mean(timeit.repeat(setup="a = []", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.054 +/- 0.025 msec

# Python array with append()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.append(1.0)", number=1000, repeat=5000)) * 1000
# 0.104 +/- 0.025 msec

# Numpy array with append()
np.mean(timeit.repeat(setup="import numpy as np; a = np.array([])", stmt="np.append(a, [1.0])", number=1000, repeat=5000)) * 1000
# 5.183 +/- 0.950 msec

# Python list using +=
np.mean(timeit.repeat(setup="a = []", stmt="a += [1.0]", number=1000, repeat=5000)) * 1000
# 0.062 +/- 0.021 msec

# Python array using += 
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a += array.array('f', [1.0]) ", number=1000, repeat=5000)) * 1000
# 0.289 +/- 0.043 msec

# Python list using extend()
np.mean(timeit.repeat(setup="a = []", stmt="a.extend([1.0])", number=1000, repeat=5000)) * 1000
# 0.083 +/- 0.020 msec

# Python array using extend()
np.mean(timeit.repeat(setup="import array; a = array.array('f')", stmt="a.extend([1.0]) ", number=1000, repeat=5000)) * 1000
# 0.169 +/- 0.034
Hephaestus
sumber