6.7. Näkymät ja kopiot

Näkymä on toinen ikkuna samaan datalohkoon kuin lähde. Dataa ei kopioida; näkymä pitää uutta kuvaajaa (omaa muotoaan, askelväliään ja dtype-tyyppiään) mutta jakaa puskurin. Näkymät ovat käytännössä ilmaisia.

Kopio pyytää kameralta uuden puskurin ja käy lähteen läpi täyttäen sen. Kopiot maksavat sekä aikaa että RAM-muistia.

Useimmat muotoa muuttavat metodit tuottavat näkymiä. Useimmat dataa muuntavat metodit tuottavat kopioita. Sen tietäminen, kumpi on kumpi, ratkaisee, käyttääkö kuuma silmukka kameran RAM-muistin loppuun.

6.7.1. Reshape

reshape() palauttaa pyydetyn muotoisen taulukon. Alkioiden kokonaismäärän on pysyttävä muuttumattomana, tai nostetaan ValueError-poikkeus:

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

Tulos on näkymä – m ja a jakavat datan. Kirjoittaminen kautta m[0, 0] = 99 muuttaa myös a[0]:n.

Uuden monikon sijoittaminen shape-attribuuttiin on lyhennysmerkintä samalle operaatiolle:

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

6.7.2. Transpose

transpose() (tai .T-oikotie) kääntää akselit. Toteutettu kääntämällä askelvälit – dataa ei siirretä:

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

Transponoitu näkymä ei käy datalohkoa läpi yhtenäisesti. Yllä olevan t:n lukeminen rivi riviltä käy muistisijainneissa 0, 3, 1, 4, 2, 5, ei taustalla olevassa 0, 1, 2, 3, 4, 5 -järjestyksessä, johon tavut on aseteltu. Tavallinen aritmetiikka ja redusoinnit käsittelevät tämän hyvin – ne etenevät askelvälien läpi – mutta tobytes() ei voi, koska se palauttaa taustalla olevan puskurin suoraan kopioimatta. Puskurin pitämät tavut eivät vastaa näkymän muodon edellyttämää järjestystä, joten metodi nostaa ValueError-poikkeuksen mille tahansa ei-yhtenäiselle näkymälle. Kun tavuja tarvitaan transponoidussa järjestyksessä, pakota ensin uusi yhtenäinen kopio:

bytes_out = t.copy().tobytes()

6.7.3. Flatten ja flat

flatten() palauttaa taulukon 1-ulotteisen kopion

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

Välitä order='C' (oletus) käydäksesi viimeisen akselin ensin tai order='F' käydäksesi ensimmäisen akselin ensin:

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 on iteraattorimuoto. Se tuottaa minkä tahansa asteen ndarray:n jokaisen alkion skalaareina ilman litteän kopion varaamista:

for x in m.flat:
    print(x)

Kun sovelluksen täytyy käydä läpi jokainen alkio, suosi flat:ia; kun se tarvitsee tiheän 1-ulotteisen puskurin annettavaksi toiselle funktiolle, käytä flatten():ia.

6.7.4. Iterointi

1-ulotteisen taulukon iterointi tuottaa skalaareja; korkeamman asteen taulukon iterointi tuottaa (n-1)-ulotteisia näkymiä:

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])

Matriisia iteroitaessa tuotetut rivit ovat näkymiä, joten niiden muokkaaminen muokkaa lähdettä.

6.7.5. Kopiot

copy() on eksplisiittinen tapa saada riippumaton ndarray, jonka muokkaukset eivät vaikuta alkuperäiseen. Uusi puskuri varataan ja lähde käydään siihen läpi:

c = a.copy()

tobytes() palauttaa bytearray:n, joka jakaa muistia taulukon datalohkon kanssa. Bytearray-puskurin kautta kirjoittaminen muokkaa taulukkoa paikallaan. Nostaa ValueError-poikkeuksen, jos taulukko ei ole tiheä (viipaloitu näkymä, transpoosi, …).

tolist() palauttaa sisällön mahdollisesti sisäkkäisenä Python-list:nä. Hyödyllinen pienten tulosten sarjallistamiseen; kallis suurille, koska jokaisesta alkiosta tulee erillinen Python-olio.

6.7.6. Mitkä operaatiot palauttavat mitäkin

Täysi sääntö:

Seuraavat operaatiot palauttavat näkymiä:

  • viipalointi – a[1:5], a[::2], m[:, 0];

  • korkeamman asteen taulukon yhden akselin indeksointi – m[0];

  • n-ulotteisen taulukon iterointi;

  • reshape(), kun pyydetty asettelu on yhteensopiva;

  • transpose() / .T;

  • frombuffer();

  • asarray(), kun dtype täsmää.

Seuraavat operaatiot palauttavat kopioita:

Käytä eksplisiittistä kopiota vain silloin, kun riippumatonta puskuria todella tarvitaan. Kamerassa, jossa RAM on rajallinen, ero näkymän ja kopion välillä on usein ero koodin, joka mahtuu, ja koodin, joka ei mahdu, välillä.