#python #list #performance #slice #assign
#python #Список #Производительность #фрагмент #назначить
Вопрос:
Если у меня есть список Python l
, каков наиболее эффективный (самый быстрый и высокоскоростной) способ присвоить то же значение v
фрагменту [start : stop : step]
(например, для положительного step
значения) этого списка?
Для моей задачи мне нужна только мелкая копия (ссылка на копию). Также в качестве расширения моей задачи было бы интересно узнать эффективные способы присвоения того же значения при глубоком копировании.
Являются ли следующие два метода самыми быстрыми из возможных способов? Или существуют другие методы, которые намного быстрее?
l[start : stop : step] = [v] * ((stop - start step - 1) // step)
и:
for i in range(start, stop, step):
l[i] = v
тайминги:
python -m timeit -s "l = list(range(10 ** 6)); start, stop, step, v = 10, 100000, 2, 99" "l[start : stop : step] = [v] * ((stop - start step - 1) // step)"
200 loops, best of 5: 1.24 msec per loop
python -m timeit -s "l = list(range(10 ** 6)); start, stop, step, v = 10, 100000, 2, 99" "for i in range(start, stop, step): l[i] = v"
50 loops, best of 5: 5.38 msec per loop
Итак, первый вариант 4.3x
в разы быстрее.
Первый вариант требует ненужного создания иногда большого списка одинаковых v
значений, также при присвоении фрагменту списка python действительно может воссоздать весь список l
! Второе решение использует медленный цикл чистого Python.
Но что мне действительно нужно, так это какая-то встроенная быстрая ( C
на основе) стандартная функция Python, например l.set_to_range(slice(start, stop, step), v)
, есть ли что-нибудь подобное? (по крайней мере, для step = 1
). То же, что и в стандартной библиотеке C
exists std::fill для выполнения этой задачи для step=1: std::fill(vec.begin() start, vec.begin() stop, v)
.
Или, если не существует встроенного метода, я ищу предложения о том, какие другие более быстрые методы (кроме двух приведенных выше) существуют.
Комментарии:
1. «Эффективный» по какой метрике? Если вы имеете в виду время, то что вы получили, когда рассчитали время для двух методов (см.
timeit
), И что вас все еще беспокоит?2. @Prune Эффективное означает самое быстрое.
3. @Prune Я не измерял эти два метода, потому что моя задача — не сравнивать эти два метода, а найти канонический самый быстрый способ сделать это. Я привел эти методы только для примера одного из способов (возможно, не самого быстрого) достижения задачи. В основном я искал встроенный метод.
4. @Prune Может быть, вы пропустили — поняли, чего я действительно хотел. Я не хотел сравнивать эти два метода, я могу сравнить их сам по timeit. Я хочу найти какой-нибудь другой новый метод, который является самым быстрым. Но если таковых не существует, я буду использовать эти два в своем коде.
5. Кто-то проголосовал за закрытие вопроса. Что в этом плохого?