Инициализация списка на известное количество элементов в Python [дубликат]
этот вопрос уже есть ответ здесь:
сейчас я использую список, и ожидал что-то вроде:
verts = list (1000)
должен ли я использовать массив вместо этого?
9 ответов:
первое, что приходит мне на ум:
verts = [None]*1000но вам действительно нужно предварительно инициализировать его?
не совсем уверен, почему все это дает вам трудное время для желающих это сделать - есть несколько сценариев, где вы хотите фиксированный размер списка инициализации. И вы правильно сделали вывод, что массивы являются разумными в этих случаях.
import array verts=array.array('i',(0,)*1000)для непифонистов,
(0,)*1000термин создает кортеж, содержащий 1000 нулей. Запятая заставляет python распознавать(0)как кортеж, в противном случае он будет оцениваться как 0.я использовал кортеж вместо списка потому что они, как правило, имеют более низкие накладные расходы.
один очевидный и, вероятно, не эффективный способ
verts = [0 for x in range(1000)]обратите внимание, что это может быть расширено до 2-размерности легко. Например, чтобы получить "массив" 10x100, вы можете сделать
verts = [[0 for x in range(100)] for y in range(10)]
желание инициализировать массив фиксированного размера является вполне приемлемой вещью для любого языка программирования; это не похоже на то, что программист хочет поместить оператор break в цикл while(true). Поверьте мне, особенно если элементы просто будут перезаписаны, а не просто добавлены/вычитаны, как в случае многих алгоритмов динамического программирования, вы не хотите возиться с операторами добавления и проверять, не был ли элемент инициализирован еще на лету (это a много кода джентльменов).
object = [0 for x in range(1000)]Это будет работать для того, что программист пытается достичь.
@Стив уже дал хороший ответ на ваш вопрос:
verts = [None] * 1000предупреждение: как указал @Joachim Wuttke, список должен быть инициализирован неизменяемым элементом.
[[]] * 1000не работает, как ожидалось, потому что вы получите список из 1000 одинаковых списков (аналогично списку из 1000 точек в том же списке в C). Неизменяемые объекты, такие как int, str или Кортеж, будут работать нормально.варианты
изменение размеров списков происходит медленно. Следующие результаты не очень удивительно:
>>> N = 10**6 >>> %timeit a = [None] * N 100 loops, best of 3: 7.41 ms per loop >>> %timeit a = [None for x in xrange(N)] 10 loops, best of 3: 30 ms per loop >>> %timeit a = [None for x in range(N)] 10 loops, best of 3: 67.7 ms per loop >>> a = [] >>> %timeit for x in xrange(N): a.append(None) 10 loops, best of 3: 85.6 ms per loopно изменение размера не очень медленным, если у вас нет очень больших списков. Вместо инициализации списка одним элементом (например,
None) и фиксированной длины, чтобы избежать изменения размера списка, вы должны рассмотреть возможность использования списка понимания и непосредственно заполнить список правильными значениями. Например:>>> %timeit a = [x**2 for x in xrange(N)] 10 loops, best of 3: 109 ms per loop >>> def fill_list1(): """Not too bad, but complicated code""" a = [None] * N for x in xrange(N): a[x] = x**2 >>> %timeit fill_list1() 10 loops, best of 3: 126 ms per loop >>> def fill_list2(): """This is slow, use only for small lists""" a = [] for x in xrange(N): a.append(x**2) >>> %timeit fill_list2() 10 loops, best of 3: 177 ms per loopсравнение с numpy
для огромного набора данных numpy или другие оптимизированные библиотеки намного быстрее:
from numpy import ndarray, zeros %timeit empty((N,)) 1000000 loops, best of 3: 788 ns per loop %timeit zeros((N,)) 100 loops, best of 3: 3.56 ms per loop
вы могли бы сделать это:
verts = list(xrange(1000))Это даст вам список из 1000 элементов по размеру и который будет инициализирован со значениями от 0-999. Как
listтут__len__во-первых, чтобы размер нового списка должно быть достаточно эффективны.
можно использовать
dictвведите вместо предварительно инициализированного списка. Стоимость словарям мала и сопоставима со стоимостью доступа к произвольному элементу списка.и при использовании отображения вы можете написать:
aDict = {} aDict[100] = fetchElement() putElement(fetchElement(), fetchPosition(), aDict)и
putElementфункция может хранить деталь на любом, Котор дали положении. И если вам нужно проверить, содержит ли ваша коллекция элемент по заданному индексу, то лучше написать:if anIndex in aDict: print "cool!"чем:
if not myList[anIndex] is None: print "cool!"так как последнее предполагает, что нет реальные элемент в вашей коллекции может быть
None. И если это произойдет-ваш код плохо себя ведет.и если вам отчаянно нужна производительность, и именно поэтому вы пытаетесь предварительно инициализировать свои переменные и написать максимально быстрый код-измените свой язык. Самый быстрый код не может быть написан на Python. Вместо этого вы должны попробовать C и реализовать оболочки для вызова вашего предварительно инициализированного и предварительно скомпилированного кода из Питон.
Это:
lst = [8 for i in range(9)]создает список, элементы инициализируются 8
а это:
lst = [0] * 7создать 7 списков, которые имеют один элемент
Не зная больше о предметной области, трудно ответить на ваш вопрос. Если вы не уверены, что вам нужно сделать что-то еще, питонический способ инициализации списка:
verts = []вы действительно видите проблемы с производительностью? Если да, то какова производительность? Не пытайтесь решить проблему, которой у вас нет. Вполне вероятно, что стоимость производительности для динамического заполнения массива до 1000 элементов составляет абсолютно не имеет значения для программу что ты действительно пытаешься писать.
класс array полезен, если вещи в вашем списке всегда будут определенным примитивным типом фиксированной длины (например, char, int, float). Но, это не требует предварительной инициализации либо.
Comments