Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Licence CC BY-NC-ND Thierry Parmentelat & Arnaud Legout Inria - UCA

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 np

Dans 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.dtype
dtype('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.dtype
dtype('float64')
# et avec un complexe
c = np.array([1, 2, 4, 8j])
c.dtype
dtype('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.dtype
dtype('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
a
The 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 :

# 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_1
np.True_
# mais bien entendu ce ne sont pas les mêmes objets
np_1 is py_1
False

Du 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)
1000112

Je 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.dtype
dtype('int64')
a.itemsize
8
c.dtype
dtype('complex128')
c.itemsize
16