6.7. View dan copy

Sebuah view adalah jendela kedua ke blok data yang sama dengan sumber. Tidak ada data yang disalin; view menyimpan deskriptor baru (shape, strides, dan dtype-nya sendiri) tetapi berbagi buffer. View pada dasarnya gratis.

Sebuah copy meminta kamera untuk buffer baru dan menelusuri sumber untuk mengisinya. Copy membutuhkan waktu dan RAM.

Sebagian besar metode pengubah bentuk menghasilkan view. Sebagian besar metode pengubah data menghasilkan copy. Mengetahui mana yang mana menentukan apakah loop panas menjalankan kamera kehabisan RAM.

6.7.1. Reshape

reshape() mengembalikan array dengan shape yang diminta. Jumlah total elemen harus tidak berubah atau ValueError dimunculkan:

a = np.arange(12, dtype=np.uint8)
m = a.reshape((3, 4))

Hasilnya adalah view -- m dan a berbagi data. Menulis melalui m[0, 0] = 99 juga mengubah a[0].

Menetapkan tuple baru ke shape adalah singkatan untuk operasi yang sama:

a = np.arange(9)
a.shape = (3, 3)

6.7.2. Transpose

transpose() (atau pintasan .T) membalik sumbu. Diimplementasikan dengan membalik stride -- tidak ada data yang dipindahkan:

m = np.arange(6, dtype=np.uint8).reshape((2, 3))
t = m.T                  # shape (3, 2), shares m's buffer

View yang ditranspose tidak menelusuri blok data secara kontinu. Membaca t di atas baris demi baris mengunjungi posisi memori 0, 3, 1, 4, 2, 5, bukan urutan 0, 1, 2, 3, 4, 5 yang mendasari di mana byte-byte tersebut ditata. Aritmetika biasa dan reduksi menangani hal itu dengan baik -- mereka melangkah melalui stride -- tetapi tobytes() tidak bisa, karena ia mengembalikan buffer yang mendasari secara langsung tanpa menyalin. Byte yang dipegang buffer tidak cocok dengan urutan yang diimplikasikan shape view, sehingga metode ini memunculkan ValueError pada view non-kontinu apa pun. Ketika byte diperlukan dalam urutan yang ditranspose, paksa salinan kontinu baru terlebih dahulu:

bytes_out = t.copy().tobytes()

6.7.3. Flatten dan flat

flatten() mengembalikan copy 1-D dari array:

f = m.flatten()          # new dense 1-D ndarray

Berikan order='C' (default) untuk menelusuri sumbu terakhir pertama atau order='F' untuk sumbu pertama pertama:

m = np.arange(6, dtype=np.uint8).reshape((2, 3))
# m = [[0, 1, 2],
#      [3, 4, 5]]
m.flatten()              # array([0, 1, 2, 3, 4, 5], dtype=uint8)
m.flatten(order='F')     # array([0, 3, 1, 4, 2, 5], dtype=uint8)

flat adalah bentuk iterator. Ia menghasilkan setiap elemen dari ndarray berperingkat apa pun sebagai skalar, tanpa mengalokasikan salinan datar:

for x in m.flat:
    print(x)

Ketika aplikasi perlu menelusuri setiap elemen, lebih baik gunakan flat; ketika membutuhkan buffer 1-D padat untuk diteruskan ke fungsi lain, gunakan flatten().

6.7.4. Iterasi

Mengiterasi array 1-D menghasilkan skalar; mengiterasi array berperingkat lebih tinggi menghasilkan view berdimensi (n-1)

m = np.array([[0, 1, 2], [3, 4, 5]], dtype=np.uint8)
for row in m:
    print(row)               # array([0, 1, 2]), array([3, 4, 5])

Baris yang dihasilkan dengan mengiterasi matriks adalah view, sehingga memodifikasinya memodifikasi sumber.

6.7.5. Copy

copy() adalah cara eksplisit untuk mendapatkan ndarray independen yang modifikasinya tidak mempengaruhi aslinya. Buffer baru dialokasikan dan sumber ditelusuri ke dalamnya:

c = a.copy()

tobytes() mengembalikan bytearray yang berbagi memori dengan blok data array. Penulisan melalui bytearray memodifikasi array di tempat. Memunculkan ValueError jika array tidak padat (view yang di-slice, transpose, ...).

tolist() mengembalikan isi sebagai Python list yang mungkin bersarang. Berguna untuk menserialisasi hasil kecil; mahal untuk yang besar, karena setiap elemen menjadi objek Python terpisah.

6.7.6. Operasi mana yang mengembalikan apa

Aturan lengkapnya:

Operasi berikut mengembalikan view:

  • slicing -- a[1:5], a[::2], m[:, 0];

  • pengindeksan sumbu tunggal dari array berperingkat lebih tinggi -- m[0];

  • mengiterasi array n-D;

  • reshape(), ketika tata letak yang diminta kompatibel;

  • transpose() / .T;

  • frombuffer();

  • asarray(), ketika dtype cocok.

Operasi berikut mengembalikan copy:

Gunakan copy eksplisit hanya ketika buffer independen benar-benar diperlukan. Pada kamera dengan RAM terbatas, perbedaan antara view dan copy sering kali menjadi perbedaan antara kode yang muat dan yang tidak.