6.7. Nézetek és másolatok

Egy nézet egy második ablak ugyanarra az adatblokkra, mint a forrás. Nem másolódik adat; a nézet egy friss leírót tart (saját alakkal, lépésközökkel és dtype-pal), de osztozik a pufferen. A nézetek lényegében ingyenesek.

Egy másolat egy új puffert kér a kamerától, és bejárja a forrást, hogy feltöltse. A másolatok időbe és RAM-ba is kerülnek.

A legtöbb alakváltoztató metódus nézeteket állít elő. A legtöbb adatátalakító másolatokat. Annak tudása, hogy melyik melyik, eldönti, hogy egy forró ciklus kifogyasztja-e a kamerát a RAM-ból.

6.7.1. Reshape

A reshape() a kért alakú tömböt adja vissza. Az elemek teljes számának változatlannak kell maradnia, különben ValueError kivétel keletkezik:

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

Az eredmény egy nézet – az m és az a megosztja az adatokat. Az m[0, 0] = 99 keresztüli írás az a[0]-t is megváltoztatja.

Egy új n-es rendezett rekord hozzárendelése a shape attribútumhoz ugyanennek a műveletnek a rövidített formája:

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

6.7.2. Transzponálás

A transpose() (vagy a .T rövidítés) megfordítja a tengelyeket. A lépésközök megfordításával valósul meg – nem mozog adat:

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

Egy transzponált nézet nem összefüggően járja be az adatblokkot. A fenti t soronkénti olvasása a 0, 3, 1, 4, 2, 5 memóriapozíciókat látogatja meg, nem azt az alapul szolgáló 0, 1, 2, 3, 4, 5 sorrendet, amelyben a bájtok elhelyezkednek. A közönséges aritmetika és a redukciók ezt jól kezelik – a lépésközökön keresztül lépkednek –, de a tobytes() nem, mert az alapul szolgáló puffert közvetlenül, másolás nélkül adja vissza. A pufferben lévő bájtok nem felelnek meg annak a sorrendnek, amelyet a nézet alakja sugall, így a metódus bármilyen nem összefüggő nézet esetén ValueError kivételt vált ki. Ha a bájtokra a transzponált sorrendben van szükség, először kényszeríts ki egy friss összefüggő másolatot:

bytes_out = t.copy().tobytes()

6.7.3. Flatten és flat

A flatten() a tömb egy 1 dimenziós másolatát adja vissza:

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

Add meg az order='C' (alapértelmezett) értéket az utolsó tengely előbb történő bejárásához, vagy az order='F' értéket az első tengely előbb történő bejárásához:

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)

A flat az iterátor forma. Bármilyen rangú ndarray minden elemét skalárként adja át, anélkül, hogy lapos másolatot foglalna:

for x in m.flat:
    print(x)

Ha az alkalmazásnak be kell járnia minden elemet, részesítsd előnyben a flat-et; ha egy sűrű 1 dimenziós pufferre van szüksége, amelyet átadhat egy másik függvénynek, használd a flatten()-t.

6.7.4. Iteráció

Egy 1 dimenziós tömb iterálása skalárokat ad; egy magasabb rangú tömb iterálása (n-1) dimenziós nézeteket ad:

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

A mátrix iterálása által adott sorok nézetek, így a módosításuk a forrást módosítja.

6.7.5. Másolatok

A copy() az explicit módja annak, hogy egy független ndarray-t kapj, amelynek módosításai nem érintik az eredetit. Egy új puffer foglalódik, és a forrás kerül bejárásra bele:

c = a.copy()

A tobytes() egy bytearray objektumot ad vissza, amely a tömb adatblokkjával megosztja a memóriát. A bytearray-en keresztüli írások helyben módosítják a tömböt. ValueError kivételt vált ki, ha a tömb nem sűrű (szeletelt nézet, transzponálás, …).

A tolist() a tartalmat egy esetlegesen beágyazott Python list formájában adja vissza. Hasznos kis eredmények sorosításához; nagyok esetén költséges, mert minden elem külön Python-objektummá válik.

6.7.6. Melyik művelet mit ad vissza

A teljes szabály:

A következő műveletek nézeteket adnak vissza:

  • szeletelés – a[1:5], a[::2], m[:, 0];

  • egy magasabb rangú tömb egyetlen tengely menti indexelése – m[0];

  • egy n dimenziós tömb iterálása;

  • reshape(), ha a kért elrendezés kompatibilis;

  • transpose() / .T;

  • frombuffer();

  • asarray(), ha a dtype egyezik.

A következő műveletek másolatokat adnak vissza:

Csak akkor nyúlj explicit másolathoz, ha valóban szükség van egy független pufferre. Egy korlátozott RAM-mal rendelkező kamerán a nézet és a másolat közötti különbség gyakran a beférő kód és a be nem férő kód közötti különbség.