6.2. Ndarray#
ndarray je typ, který v numpy uchovává numerická data. Je to dvě věci v jednom: jediný kompaktní blok dat a malý deskriptor před tímto blokem, který říká, jak jej číst.
6.2.1. Uvnitř krabice#
Datový blok obsahuje všechny prvky pole jeden za druhým, bez čehokoli navíc mezi nimi. Každý prvek zabírá stejný počet bajtů – jeden u pole hodnot uint8, dva u uint16, čtyři u float. 256prvkové pole uint8 je přesně 256 bajtů dat; stejných 256 čísel v Python list zabere kilobajt – jeden 32bitový slot na prvek bez ohledu na to, jak málo bitů hodnota ve skutečnosti potřebuje.
Deskriptor zaznamenává, co blok znamená. Pět hodnot stačí k popisu libovolného obdélníkového pole bez ohledu na počet rozměrů:
dtype– typ prvku. Rozhoduje o tom, kolik bajtů každý prvek zabírá a jaký rozsah hodnot může uchovávat (probráno na stránce Dtypy).itemsize– šířka jednoho prvku v bajtech, odvozená z dtype.ndim– počet rozměrů (1 pro vektor, 2 pro matici, 3 pro objem, až do 4).shape– velikost podél každého rozměru jako n-tice.strides– jak procházet datovým blokem při průchodu každou osou. Probráno na stránce Tvar a kroky.
A to je vše. Každá rychlá cesta v numpy – aritmetika, redukce, broadcasting, řezy – pracuje přímo z těchto pěti hodnot a ukazatele na data, bez režie Pythonu na jednotlivé prvky.
6.2.2. Co tento návrh přináší#
Z konceptu „kompaktní blok + malý deskriptor“ vyplývají tři vlastnosti, které definují, jak se chová zbytek této sekce.
Matematika po prvcích běží jako jediné volání. a + b mezi dvěma poli shodného tvaru sečte dva buffery a zapíše třetí, a to vše uvnitř jednoho volání knihovny. np.sin(a) udělá totéž pro sinus každého prvku. Aritmetické, porovnávací a bitové operátory fungují všechny tímto způsobem.
Pohled na stejná data jiným způsobem je zdarma. Žádost o podoblast pole nebo o tatáž data uspořádaná pod jiným tvarem nepřesouvá žádné bajty. Operace vrátí nový deskriptor ukazující na tentýž datový blok. Výsledek se nazývá pohled (view) – druhé okno do téhož podkladového bufferu. Zápis přes pohled zapisuje do zdroje.
Smíšené tvary stále fungují. Kratší pole proti delšímu, řádek proti matici, sloupec proti řádku – numpy je srovná pomocí broadcastingu, malé sady pravidel, která rozhodují, která krátká osa se roztáhne, aby odpovídala dlouhé. Roztažení je virtuální; žádná data se neduplikují.
6.2.3. Co tento návrh stojí#
Ze stejného návrhu vyplývají dvě omezení.
Každý prvek má stejný typ. Seznam může obsahovat int vedle str vedle seznamu tří dalších hodnot int; ndarray nemůže. Dtype je pevně dán v době konstrukce. Stránka Dtypy probírá malou sadu typů, které numpy podporuje, a pravidla, jež vyplývají z toho, že je typ pevně daný.
Zvětšení pole není zdarma. Seznam si na konci ponechává volné sloty a levně podporuje .append. ndarray má přesně takovou velikost, jakou potřebuje; přidání by znamenalo alokovat nový, větší buffer a zkopírovat do něj starý obsah. Metoda append() záměrně neexistuje. Správným vzorem na kameře je předalokovat cíl na jeho konečnou velikost a naplnit jej; stránka Výkon tuto techniku probírá.
S kompaktním typovaným bufferem pro data, malým deskriptorem pro metadata a třemi zárukami chování (rychlá matematika po prvcích, alternativní pohledy na stejná data bez kopírování a tvary, které se broadcastují) je ndarray základem, na němž stojí zbytek této kapitoly. Jak pole vlastně vzniká – z literálu, z předvyplněné alokace, z bufferu periferie – je další praktická otázka.