Python: добавление функции в массив в цикле FOR - PullRequest
0 голосов
/ 28 августа 2011

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

myArray = zeros(x)   
for i in range(x):
  myArray[i] = createFunction(i)

Если я запускаю это, я получаю несоответствие типов: Аргумент float () должен быть строкой или числом, а не 'функцией'

Создание массива напрямую работает хорошо:

  myArray = array([createFunction(0)...])

Но так как я не знаю, сколько функций мне нужно, это именно то, что я хочу предотвратить.

Ответы [ 4 ]

2 голосов
/ 28 августа 2011

Ах, я понял.Вы действительно имеете в виду массив функций .

Ошибка несоответствия типов возникает из-за того, что при вызове zeros по умолчанию создается массив с плавающей точкой.Таким образом, ваш оригинал сработал бы, если бы вместо этого вы сделали myArray = numpy.empty(x, dtype=numpy.object) (обратите внимание, что empty имеет смысл больше, чем zeros здесь)Немного более питонная версия - использовать понимание списка

myArray = numpy.array([createFunction(i) for i in range(x)]).

Но вам может вообще не понадобиться создавать пустой массив, в зависимости от того, что вы хотите с ним делать:

myArray = [createFunction(i) for i in range(x)]

Если вы хотите избежать списка, лучше использовать numpy.fromfunction вместе с numpy.vectorize:

myArray = numpy.fromfunction(numpy.vectorize(createFunction), 
                             shape=(x,), dtype=numpy.object)

, где (x,)это кортеж, дающий форму массива.Вызов vectorize необходим, потому что fromfunction предполагает, что функция может работать с массивом входных данных и возвращает массив скаляров, а vectorize преобразует функцию, чтобы сделать именно это.dtype=object необходим, так как иначе numpy пытается создать массив с плавающей точкой.

1 голос
/ 29 августа 2011

Массивы Numpy являются однородными.То есть все элементы массива numpy относятся к одному и тому же типу - python типизирован по утке, numpy - нет.Это часть того, что делает матричные операции над массивами и матрицами такими быстрыми.Однако из-за этого тип данных должен быть известен при первом создании массива.Numpy, как правило, очень хорошо выводит тип данных.Проблема возникает при создании пустого или обнуленного массива.Поскольку нет элементов для проверки, numpy должен угадать тип данных.Numpy по умолчанию принимает значение numpy.float64, если ему не присвоен тип данных во время создания массива.Это достойный выбор, поскольку numpy обычно используется в научных или технических областях, где требуются числа с плавающей запятой.Именно поэтому numpy жалуется - потому что он не может хранить ваши функции как 64-битные числа с плавающей запятой.

Быстрое решение состоит в том, чтобы сообщить numpy тип данных, который вы хотите.например.

myArray = numpy.zeros(x, dtype=numpy.object)

Обратите внимание, что тип данных не может быть любым классом, но должен быть экземпляром numpy.dtype (для расширенного использования вы можете создать дополнительные dtypes среды выполнения, которыми затем может управлять numpy).Для функций numpy будет хранить их как numpy.object (что означает любой универсальный объект python).Я не думаю, что вы получите какой-либо выигрыш в производительности от использования NumPy для хранения массивов функций.Возможно, вам было бы лучше создать генераторные функции и объединить их в цепочку, преобразовав их в пустой массив, если вы знаете, что результатом будет число.

funcs = [createFunction(i) for i in xrange(x)]

def getItemFromEachFunction(i):
    return funcs[i]()

arr = numpy.fromfunction(getItemFromEachFunction, (x,))
1 голос
/ 28 августа 2011

Если вам нужен массив функций, возможно ли не использовать NumPy?Массивы NumPy имеют типы в стиле C, и по умолчанию они плавают.Если вы можете, просто используйте стандартный список Python.Но если вам абсолютно необходимо использовать NumPy, попробуйте определить массив следующим образом:

import numpy as np
a = np.empty([x], dtype=np.dtype(np.object_))

Или же вам нужно, чтобы он был с , что dtype.

1 голос
/ 28 августа 2011

Может быть, вы можете использовать

myArray = array([createFunction(i) for i in range(x)])
...