web-dev-qa-db-fra.com

Création efficace de tableaux numpy à partir de la compréhension de listes et en général

Dans mon travail actuel, j'utilise beaucoup Numpy et les listes de compréhension et dans l'intérêt des meilleures performances possibles, j'ai les questions suivantes:

Que se passe-t-il réellement dans les coulisses si je crée un tableau Numpy comme suit? :

a = numpy.array( [1,2,3,4] )

Je suppose que python crée d'abord une liste ordinaire contenant les valeurs, puis utilise la taille de la liste pour allouer un tableau numpy et copie ensuite les valeurs dans ce nouveau tableau. Est-ce correct, ou est-ce le interprète assez intelligent pour se rendre compte que la liste est seulement intermédiaire et au lieu de cela copier les valeurs directement?

De même, si je souhaite créer un tableau numpy à partir de la compréhension de la liste en utilisant numpy.fromiter ():

a = numpy.fromiter( [ x for x in xrange(0,4) ], int )

cela entraînera-t-il la création d'une liste intermédiaire de valeurs avant d'être introduite dans fromiter ()?

Cordialement Niels

36
NielsGM

Je crois que la réponse que vous recherchez utilise generator expressions avec numpy.fromiter .

numpy.fromiter((<some_func>(x) for x in <something>),<dtype>,<size of something>)

Les expressions de générateur sont paresseuses - elles évaluent l'expression lorsque vous les parcourez.

L'utilisation des compréhensions de liste crée la liste, puis l'introduit dans numpy, tandis que les expressions de générateur en produisent une à la fois.

Python évalue les choses à l'intérieur -> à l'extérieur, comme la plupart des langues (sinon toutes), donc en utilisant [<something> for <something_else> in <something_different>] ferait la liste, puis itérerait dessus.

40
Snakes and Coffee

Vous pouvez créer votre propre liste et l'expérimenter pour faire la lumière sur la situation ...

>>> class my_list(list):
...     def __init__(self, arg):
...         print 'spam'
...         super(my_list, self).__init__(arg)
...   def __len__(self):
...       print 'eggs'
...       return super(my_list, self).__len__()
... 
>>> x = my_list([0,1,2,3])
spam
>>> len(x)
eggs
4
>>> import numpy as np
>>> np.array(x)
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])
>>> np.fromiter(x, int)
array([0, 1, 2, 3])
>>> np.array(my_list([0,1,2,3]))
spam
eggs
eggs
eggs
eggs
array([0, 1, 2, 3])
8
wim