Эффективное одновременное обновление объектов в списке, возможно, с использованием копирования. Как?
Предположим, у меня есть список g (На практике это список с двумя вложениями, который состоит из трех измерений, но здесь для ясности он упрощен до одного измерения.)
g = [1,2,3,2,1]
Я хочу функцию, которая может сделать g[x] = g[x-1]+g[x]. Неправильный путь будет
def f(thing):
for x in xrange(0,len(thing)):
thing[x] += thing[x-1]
f(g)
что неправильно, потому что он обновляет целые числа один за другим, а не все сразу. Альтернативой является копирование g.
gcopy = g[:]
def f(thing, copy):
for x in xrange(0,len(thing)):
thing[x] = copy[x]+copy[x-1]
g = gcopy[:]
f(g,gcopy)
Если у g есть объекты, как в моем случае, copy.deepcopy(g)
похоже на работу.
Проблема в том, что копирование становится моим узким местом в производительности, а глубокое копирование занимает столько же времени, сколько и весь мой код вместе взятый.
Я искал в SO и Google идеи / решения, и несколько раз провел мозговой штурм, но ни одна не казалась многообещающей.
Ответ на эту тему: /questions/22342869/python-kak-skopirovat-obekt-effektivnyim-sposobom-kotoryij-takzhe-pozvolyaet-ego-modifitsirovat/22342882#22342882, предлагает вернуть объекты вместо их изменения. Я смущен тем, что это влечет за собой все же. Как помогает возврат измененных объектов?
Я слышал, что копирование объектов вычислительно дорого с глубокой копией. Если это так, возможное решение состоит в том, чтобы заменить объекты списками и сохранить атрибуты объектов как целые числа и числа с плавающей точкой в списке. Это приводит к тому, что все становится почти нечитаемым, и может стать еще более запутанным, поскольку у меня есть подклассы и наследование. Поскольку есть только списки, можно надеяться, что тогда можно будет скопировать каждый список, подсписок, подсписок и т. Д. И собрать их. Вероятно, не очень хорошее решение, и сомнительно, что ускорение является существенным (хотя я не проверял его).
Подводя итог, существует ли способ более эффективно одновременно изменять значения каждого объекта в списке с копированием списка или без него? Или я застрял с глубокой копией? Спасибо!
2 ответа
В общем, я не думаю, что вы найдете быстрый способ редактирования списка на месте с такой зависимостью от данных. Обратная итерация будет работать, если вы зависите только от предыдущих элементов. Прямая итерация будет работать, если у вас есть только прямые зависимости. Если у вас есть оба, вам понадобятся временные переменные для хранения исходных значений, пока они больше не нужны. Особенно в случае многомерных списков это может оказаться менее эффективным, чем просто копирование списков.
Вы можете использовать массивы numpy, чтобы делать то, что вы хотите? Numpy хорошо справляется с подобной операцией, и, хотя она в конечном итоге делает копию, гораздо быстрее копировать пустой массив, чем выполнять deepcopy() вложенного списка.
Если честно, я понятия не имею, что ты делаешь. Но вы пробовали обратную итерацию? Это мощная техника.
def f(thing):
for x in xrange(len(thing) -1, 0, -1):
thing[x] += thing[x-1]
f(g)
Это позволит вам обновляться без проблем. Вы также можете использовать обратную итерацию для удаления элементов из списка. По сути, любая операция, которая опирается только на предыдущие элементы последовательности, остающиеся стабильными, может быть выполнена с помощью обратной итерации.
Если вы хотите сделать дополнительно g[0] = g[0] + g[len(g)-1]
затем измените "0" в приведенном выше коде на "-1". Это скажет петле пойти еще дальше.