Setiap operasi yang kita tulis sejauh ini — a + b, np.sqrt(a), a * 0.9 — mengalokasikan array baru untuk hasilnya. Pada array kecil perilaku itu tidak terasa, tetapi pada array ratusan megabita yang dioperasikan berulang kali, alokasi yang terus-menerus membebani memori dan memperlambat program. NumPy menyediakan jalur kedua: operasi in-place, yang mengubah isi buffer array yang sama tanpa membuat array baru.

Bab ini membahas dua alat in-place dan satu batasannya:

  • Operator augmented: +=, -=, *=, dan kawan-kawannya.
  • Parameter out pada ufunc untuk menulis hasil ke array yang telah disiapkan.
  • Batasan dtype: operasi in-place tidak boleh mengubah tipe data array.

Operator augmented mengubah array langsung #

Operator augmented Python berperilaku khusus pada array NumPy: alih-alih membuat array baru, NumPy mengubah buffer array asli:

python
import numpy as np

stok = np.array([10, 20, 30])
stok += 5
print(stok)
stok -= 3
print(stok)
stok *= 2
print(stok)

Output yang Dihasilkan:

text
[15 25 35]
[12 22 32]
[24 44 64]
  1. Baris 4 (stok += 5): setiap elemen stok ditambah 5 di tempatnya. Buffer array 10, 20, 30 langsung menjadi 15, 25, 35; tidak ada array kedua yang lahir.
  2. Baris 6 (stok -= 3): pengurangan in-place memakai buffer yang sama lagi.
  3. Baris 8 (stok *= 2): perkalian in-place; hasil akhir 24, 44, 64 tinggal di objek stok yang pertama.

Daftar lengkap operator augmented dan catatannya:

OperatorKeterangan
a += bpenjumlahan in-place
a -= bpengurangan in-place
a *= bperkalian in-place
a //= bpembagian lantai in-place
a %= bsisa bagi in-place
a **= bpangkat in-place
a /= bpembagian in-place; menuntut array float karena hasil / selalu float

a = a + b dan a += b tidak sama #

Perbedaan paling penting terlihat ketika dua nama menunjuk array yang sama. Bentuk a = a + 10 membuat array baru; bentuk a += 10 mengubah buffer lama:

python
import numpy as np

a = np.array([1, 2, 3])
b = a
a = a + 10
print(b)
c = np.array([1, 2, 3])
d = c
c += 10
print(d)

Output yang Dihasilkan:

text
[1 2 3]
[11 12 13]
  1. Baris 5 (a = a + 10): sisi kanan dihitung menjadi array baru berisi 11, 12, 13, lalu nama a dipindahkan menunjuk array baru itu. b masih menunjuk array lama, sehingga masih mencetak [1 2 3].
  2. Baris 8 (c += 10): tidak ada array baru; buffer yang dibagi c dan d diubah langsung, sehingga d ikut melihat [11 12 13].
EkspresiYang terjadiNama lain yang menunjuk array yang sama
a = a + 10array baru dibuat; a menunjuk array barutidak terpengaruh
a += 10buffer array lama diubahikut berubah

Batasan dtype: in-place tidak mengubah tipe #

Operasi in-place wajib menampung hasil ke dtype yang sudah ada. Ketika hasil tidak muat, NumPy menolak operasi tersebut:

python
import numpy as np

a = np.array([1, 2, 3])
try:
    a += np.array([0.5, 0.5, 0.5])
except TypeError as e:
    print(type(e).__name__)
    print(e)
a = a + np.array([0.5, 0.5, 0.5])
print(a)

Output yang Dihasilkan:

text
UFuncTypeError
Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
[1.5 2.5 3.5]
  1. Blok try (baris 4-8): a bertipe int64, sedangkan hasil penjumlahan dengan float bertipe float64. Menampung float64 ke buffer int64 berarti memotong informasi, sehingga NumPy melempar UFuncTypeError dengan aturan casting same_kind.
  2. Baris 9 (a = a + ...): bentuk penugasan biasa bebas dari batasan itu karena array baru ber-dtype float64 dibuat — hasilnya [1.5 2.5 3.5].

Jika memang ingin buffer int menerima tambahan pecahan, konversikan lebih dahulu dengan a = a.astype(np.float64) — perilaku konversi dibahas pada Chapter Konversi Tipe Data.

Parameter out pada skenario hemat memori #

Parameter out pada ufunc — dikenalkan pada Chapter Fungsi Universal (ufunc) — adalah bentuk in-place yang paling fleksibel: wadah hasil berdiri sendiri, terpisah dari array masukan:

python
import numpy as np

total = np.zeros(3)
sumber = np.array([2.5, 1.0, 4.0])
np.multiply(sumber, 4, out=total)
print(total)

Output yang Dihasilkan:

text
[10.  4. 16.]
  1. Baris 3 (total = np.zeros(3)): buffer hasil dialokasikan sekali, lebih dahulu.
  2. Baris 5 (np.multiply(sumber, 4, out=total)): hasil perkalian ditulis langsung ke total; sepanjang perhitungan tidak ada array hasil baru yang dialokasikan.