6.2. ndarray¶
ndarray este tipul care conține date numerice în numpy. Este două lucruri într-unul: un singur bloc compact de date și un mic descriptor în fața acelui bloc care spune cum să fie citit.
6.2.1. În interiorul cutiei¶
Blocul de date conține fiecare element al tabloului cap la cap, fără nimic în plus între ele. Fiecare element ocupă același număr de octeți – unul pentru un tablou de valori uint8, doi pentru uint16, patru pentru float. Un tablou uint8 cu 256 de elemente are exact 256 de octeți de date; aceleași 256 de numere într-o list Python ocupă un kilooctet – câte un slot de 32 de biți per element, indiferent de câți biți are nevoie în realitate valoarea.
Descriptorul înregistrează ce înseamnă blocul. Cinci valori sunt suficiente pentru a descrie orice tablou dreptunghiular, indiferent de câte dimensiuni are:
dtype– tipul elementelor. Decide câți octeți ocupă fiecare element și ce interval de valori poate conține (tratat pe Dtype-uri).itemsize– lățimea în octeți a unui element, derivată din dtype.ndim– numărul de dimensiuni (1 pentru un vector, 2 pentru o matrice, 3 pentru un volum, până la 4).shape– dimensiunea de-a lungul fiecărei dimensiuni, sub forma unui tuplu.strides– cum să se parcurgă blocul de date pentru a străbate fiecare axă. Tratat pe Formă și pași (strides).
Asta este tot. Fiecare cale rapidă din numpy – aritmetică, reduceri, broadcasting, feliere – funcționează direct pornind de la aceste cinci valori plus pointerul către date, fără overhead Python per element.
6.2.2. Ce aduce designul¶
Trei proprietăți decurg din „bloc compact + descriptor mic” și definesc modul în care se comportă restul secțiunii.
Operațiile matematice element cu element rulează ca un singur apel. a + b între două tablouri de formă potrivită adună cele două tampoane și scrie un al treilea, totul într-un singur apel de bibliotecă. np.sin(a) face același lucru pentru sinusul fiecărui element. Operatorii aritmetici, de comparație și pe biți funcționează cu toții în acest fel.
Privirea acelorași date dintr-un alt unghi este gratuită. Cererea unei subregiuni a unui tablou, sau a acelorași date dispuse sub o altă formă, nu mută niciun octet. Operația returnează un descriptor nou care indică spre același bloc de date. Rezultatul se numește vizualizare (view) – o a doua fereastră către același tampon de bază. Scrierea printr-o vizualizare scrie în sursă.
Formele mixte funcționează în continuare. Un tablou mai scurt față de unul mai lung, un rând față de o matrice, o coloană față de un rând – numpy le aliniază prin broadcasting, un set restrâns de reguli care decid care axă scurtă se întinde pentru a se potrivi cu cea lungă. Întinderea este virtuală; niciun fel de date nu sunt duplicate.
6.2.3. Ce costă designul¶
Două restricții decurg din același design.
Fiecare element are același tip. O listă poate conține un int lângă un str lângă o listă cu încă trei valori int; un ndarray nu poate. Dtype-ul este fixat la momentul construirii. Pagina Dtype-uri tratează setul restrâns de tipuri pe care numpy le acceptă și regulile care decurg din fixarea unuia.
Creșterea unui tablou nu este gratuită. O listă păstrează sloturi de rezervă la sfârșit și acceptă .append ieftin. Un ndarray are exact dimensiunea de care are nevoie; adăugarea ar însemna alocarea unui tampon nou, mai mare, și copierea conținutului vechi în el. Nu există metoda append(), în mod intenționat. Tiparul corect pe cameră este pre-alocarea destinației la dimensiunea sa finală și completarea ei; Performanță tratează tehnica.
Cu un tampon tipizat și compact pentru date, un mic descriptor pentru metadate și trei garanții de comportament (operații matematice rapide element cu element, vizualizări alternative ale acelorași date fără copiere și forme care fac broadcasting), ndarray este fundația pe care se sprijină restul capitolului. Cum apare de fapt un tablou – dintr-un literal, dintr-o alocare pre-completată, dintr-un tampon de la un periferic – este următoarea întrebare practică.