Complément - niveau intermédiaire¶
Nous allons voir dans ce complément ce qu’il faut savoir sur le type d’un tableau numpy.
import numpy as npDans ce complément nous allons rester en dimension 1 :
a = np.array([1, 2, 4, 8])Toutes les cellules ont le même type¶
Comme on l’a vu dans la vidéo, les très bonnes performances que l’on peut obtenir en utilisant un tableau numpy sont liées au fait que le tableau est homogène : toutes les cellules du tableau possèdent le même type :
# pour accéder au type d'un tableau
a.dtypedtype('int64')Vous voyez que dans notre cas, le système a choisi pour nous un type entier ; selon les entrées on peut obtenir :
# si je mets au moins un flottant
f = np.array([1, 2, 4, 8.])
f.dtypedtype('float64')# et avec un complexe
c = np.array([1, 2, 4, 8j])
c.dtypedtype('complex128')Et on peut préciser le type que l’on veut si cette heuristique ne nous convient pas :
# je choisis explicitement mon dtype
c2 = np.array([1, 2, 4, 8], dtype=np.complex64)
c2.dtypedtype('complex64')Pertes de précision¶
Une fois que le type est déterminé, on s’expose à de possibles pertes de précision, comme d’habitude :
a, a.dtype(array([1, 2, 4, 8]), dtype('int64'))# a est de type entier
# je vais perdre le 0.14
a[0] = 3.14
aThe history saving thread hit an unexpected error (OperationalError('database is locked')).History will not be written to the database.
array([3, 2, 4, 8])Types disponibles¶
Voyez la liste complète https://docs.scipy.org/doc/numpy/user/basics.types.html.
Ce qu’il faut en retenir :
vous pouvez choisir entre
bool,int,uint(entier non signé),floatetcomplex;ces types ont diverses tailles pour vous permettre d’optimiser la mémoire réellement utilisée ;
ces types existent en tant que tels (hors de tableaux).
# un entier sur 1 seul octet, c'est possible !
np_1 = np.int8(1)
# l'équivalent en Python natif
py_1 = 1# il y a bien égalité
np_1 == py_1np.True_# mais bien entendu ce ne sont pas les mêmes objets
np_1 is py_1FalseDu coup, on peut commencer à faire de très substantielles économies de place ; imaginez que vous souhaitez manipuler une image d’un million de pixels en noir et blanc sur 256 niveaux de gris ; j’en profite pour vous montrer np.zeros (qui fait ce que vous pensez) :
# pur Python
from sys import getsizeof
pure_py = [0 for i in range(10**6)]
getsizeof(pure_py)8448728# numpy
num_py = np.zeros(10**6, dtype=np.int8)
getsizeof(num_py)1000112Je vous signale enfin l’attribut itemsize qui vous permet d’obtenir la taille en octets occupée par chacune des cellules, et qui correspond donc en gros au nombre qui apparaît dans dtype, mais divisé par huit :
a.dtypedtype('int64')a.itemsize8c.dtypedtype('complex128')c.itemsize16