Python избегает многократного выделения большого массива

#python-3.x

#python-3.x

Вопрос:

Мне приходится вычислять функцию много-много раз. Для вычисления этой функции должны быть вычислены элементы массива. Массив довольно большой.

Как я могу избежать выделения массива при каждом вызове функции.

Код, который я пробовал, выглядит примерно так:

 class FunctionCalculator(object):
    def __init__(self, data):
        """
        Get the data and do some small handling of it
        Let's say that we do
        self.data = data
        """
    def function(self, point):
        return numpy.sum(numpy.array([somecomputations(item) for item in self.data]))
  

Что ж, возможно, мое беспокойство необоснованно, поэтому у меня сначала этот вопрос.

Вопрос: Верно ли, что массив [somecomputations(item) for item in data] выделяется и освобождается при каждом вызове function ?

Думая, что это тот случай, когда я пытался

 class FunctionCalculator(object):
    def __init__(self, data):
        """
        Get the data and do some small handling of it
        Let's say that we do
        self.data = data
        """
        self.number_of_data = range(0, len(data))
        self.my_array = numpy.zeros(len(data))
    def function(self, point):
        for i in self.number_of_data:
            self.my_array[i] = somecomputations(self.data[i])
        return numpy.sum(self.my_array)
  

Это медленнее, чем предыдущая версия. Я предполагаю, что понимание списка в первой версии может быть выполнено полностью на C, в то время как во второй версии меньшие части скрипта могут быть переведены в оптимизированный код C.

У меня очень слабое представление о том, как работает Python внутри.

Вопрос: Есть ли хороший способ пропустить выделение массива при каждом вызове функции и в то же время воспользоваться преимуществами хорошо оптимизированного цикла для массива?

Я использую Python3.5

Ответ №1:

Нет необходимости в цикле по массиву и многократном доступе python к c, отсюда и замедление. Прелесть массивов numpy в том, что функции работают с ними ячейка за ячейкой. Я думаю, что самым быстрым было бы:

 return numpy.sum(somecomputations(self.data))
  

Для некоторых вычислений может потребоваться небольшая модификация, но часто это сработает с места в карьер. Кроме того, вы не используете point и другие вещи.

Комментарии:

1. Для того, чтобы передать массив numpy в мою функцию, должна ли функция состоять из операций, о которых знает numpy? Я не совсем понял.

2. О! Я только что узнал, что есть numpy.vectorize , которому вы передаете функцию. Это может помочь.

3. Это не обязательно. Функции, которые являются простым арифметическим выражением, работают как есть.