List Python adalah wadah paling serbaguna di bahasa ini: satu list boleh berisi integer, string, bahkan list lain sekaligus, dan isinya dapat ditambah atau dibuang kapan saja. Keluwesan itu layak dimiliki saat data sedikit. Namun pada komputasi numerik, fleksibilitas list justru menjadi beban: setiap elemen adalah objek Python penuh yang diawasi interpreter.

ndarray NumPy mengambil jalan sebaliknya — kaku tetapi cepat. Bab ini membandingkan keduanya pada empat aspek (tipe data, aritmatika, memori, dan kerja di balik layar), lalu menutup dengan panduan kapan list masih menjadi pilihan yang tepat.

Perbandingan Singkat #

AspekPython listndarray NumPy
Tipe elemenheterogen, tiap elemen bebas bertipehomogen, satu dtype untuk semua elemen
Struktur memoriwadah pointer menuju objek terpisahsatu buffer kontinu berisi nilai mentah
Aritmatikaperlu loop atau comprehension manualekspresi langsung, misalnya harga * 1.1
Kecepatanoperasi ditafsirkan per objek oleh interpreteroperasi dijalankan sekali di kode C
Ukuran memoribesar: pointer plus objek per elemenkecil: nilai mentah berdempetan
Strukturbersarang bebas, dimensi boleh campurbentuk tetap (shape), perubahan dimensi eksplisit

Dua aspek pertama — tipe dan memori — menjadi akar penyebab perbedaan sisanya. Mari kita bedah satu per satu dengan bukti kode.

Aritmatika per Elemen: Loop vs Ekspresi #

Misalkan harga tiga barang naik 10 persen dan hasilnya perlu dibulatkan ke rupiah penuh. Versi list memaksa kita menulis comprehension; versi array cukup satu ekspresi:

python
import numpy as np

harga_list = [15000, 24000, 8000]
harga_np = np.array(harga_list)

naik_list = [round(h * 1.1) for h in harga_list]
naik_np = np.round(harga_np * 1.1)
print(naik_list)
print(naik_np)

Output yang Dihasilkan:

text
[16500, 26400, 8800]
[16500. 26400.  8800.]

Mari kita amati per baris:

  1. Baris 3-4: harga_np dibuat dari list yang sama, sehingga kedua versi bekerja pada data yang identik.
  2. Baris 6 (list): comprehension mengulang elemen satu per satu di level Python; round(h * 1.1) dijalankan tiga kali terpisah.
  3. Baris 7 (array): harga_np * 1.1 mengalikan seluruh elemen sekaligus di kode C, lalu np.round membulatkan hasilnya. Satu ekspresi menggantikan seluruh loop.
  4. Output: nilai keduanya sama; tanda titik pada array hanya menandakan tipenya float64.

Nilai 1.1 tidak persis terwakili di sistem biner, sehingga hasil kali mentahnya bisa berupa pecahan panjang seperti 16500.000000000002. Karena konteksnya rupiah, kita bulatkan dengan round dan np.round — sekaligus membuat perbandingan kedua output menjadi ringkas.

Penggunaan Memori #

Cara paling jujur membandingkan memori adalah mengukurnya langsung: sys.getsizeof untuk list dan atribut nbytes milik ndarray.

python
import numpy as np
import sys

data_list = list(range(256, 1256))      # 1000 bilangan bulat unik
data_np = np.arange(256, 1256)

total_list = sys.getsizeof(data_list) + sum(sys.getsizeof(x) for x in data_list)
print("Python list :", total_list, "byte")
print("NumPy int64 :", data_np.nbytes, "byte")

Output yang Dihasilkan:

text
Python list : 36056 byte
NumPy int64 : 8000 byte

Angka list dihitung dua lapis agar pengukurannya adil. sys.getsizeof(data_list) hanya mengukur wadah pointer (1000 pointer × 8 byte + header 56 byte), sedangkan setiap objek integer menempati ±28 byte di lokasi memori lain; jumlah keduanya menghasilkan 36056 byte. ndarray tidak mengalami pembengkakan itu: nbytes menunjukkan 1000 elemen × 8 byte per int64 = 8000 byte dalam satu blok. Selisih sekitar 4,5 kali ini membesar seiring jumlah data.

Rentang 256 ke atas dipilih dengan sengaja: CPython meng-cache bilangan kecil dari -5 sampai 256, sehingga bilangan di luar rentang itu membuat ukuran tiap objek konsisten dan hasil pengukuran dapat direproduksi.

Tipe Homogen vs Heterogen #

Perbedaan tipe paling terasa saat data campuran masuk. List menyimpan apa adanya; ndarray memaksa semuanya menyatu ke satu dtype:

python
import numpy as np

data_np = np.array([90, "Budi", 85.5])
print(data_np.dtype)
print(data_np)

Output yang Dihasilkan:

text
<U32
['90' 'Budi' '85.5']

Ketiga nilai dipaksa menjadi teks: tipe <U32 adalah string Unicode berlebar tetap, dan angka 90 serta 85.5 kehilangan sifat numeriknya — menghitung data_np.mean() menjadi tidak mungkin. List Python tidak mengalami masalah semacam ini karena setiap elemennya memang objek bebas.

Kapan List Tetap Pilihan Tepat #

  • Data hanya sedikit (puluhan elemen) dan dihitung sesekali.
  • Elemen campur tipe atau berstruktur bertingkat, misalnya list of dict.
  • Butuh pertumbuhan dinamis: append dan remove saat program berjalan.
  • Mengumpulkan hasil secara bertahap, lalu mengonversi sekali dengan np.array(...) di akhir.

List dan array bukan saingan yang saling menggantikan; keduanya saling melengkapi. Pola umum di lapangan: kumpulkan data dengan list, lalu olah bagian beratnya di array. Panduan keputusan lengkapnya kita rangkum pada bab Kapan Menggunakan NumPy.