Эффективные способы дублировать массив / список в Python
Примечание: яЯ разработчик Ruby, пытающийся найти свой путь в Python.
Когда я хотел выяснить, почему некоторые скрипты используютmylist[:]
вместоlist(mylist)
чтобы дублировать списки, я сделал быстрый тест различных методов для дублированияrange(10)
(см. код ниже).
РЕДАКТИРОВАТЬ: Я обновил тесты, чтобы использовать Pythontimeit
как предложено ниже. Это делает невозможным прямое сравнение с Ruby, потому чтоtimeit Безразлично»т зацикливание в то время как РубиBenchmark
делает, поэтому код Ruby дляссылка только.
Python 2.7.2
Array duplicating. Tests run 50000000 times
list(a) 18.7599430084
copy(a) 59.1787488461
a[:] 9.58828091621
a[0:len(a)] 14.9832749367
Для справки, я написал тот же скрипт на Ruby:
Ruby 1.9.2p0
Array duplicating. Tests 50000000 times
user system total real
Array.new(a) 14.590000 0.030000 14.620000 ( 14.693033)
Array[*a] 18.840000 0.060000 18.900000 ( 19.156352)
a.take(a.size) 8.780000 0.020000 8.800000 ( 8.805700)
a.clone 16.310000 0.040000 16.350000 ( 16.384711)
a[0,a.size] 8.950000 0.020000 8.970000 ( 8.990514)
Вопрос 1: что такоеmylist[:]
делать по-другому, что это25% быстрее, чем дажеmylist[0:len(mylist)]
, Копирует ли это в память напрямую или как?
Вопрос 2: редактировать: обновленные тесты небольше не видно огромных различий в Python и Ruby.было: Реализовал ли я тесты каким-то явно неэффективным способом, чтобы код на Ruby был намного быстрее, чем на Python?
Теперь код листингов:
Python:
import timeit
COUNT = 50000000
print "Array duplicating. Tests run", COUNT, "times"
setup = 'a = range(10); import copy'
print "list(a)\t\t", timeit.timeit(stmt='list(a)', setup=setup, number=COUNT)
print "copy(a)\t\t", timeit.timeit(stmt='copy.copy(a)', setup=setup, number=COUNT)
print "a[:]\t\t", timeit.timeit(stmt='a[:]', setup=setup, number=COUNT)
print "a[0:len(a)]\t", timeit.timeit(stmt='a[0:len(a)]', setup=setup, number=COUNT)
Рубин:
require 'benchmark'
a = (0...10).to_a
COUNT = 50_000_000
puts "Array duplicating. Tests #{COUNT} times"
Benchmark.bm(16) do |x|
x.report("Array.new(a)") {COUNT.times{ Array.new(a) }}
x.report("Array[*a]") {COUNT.times{ Array[*a] }}
x.report("a.take(a.size)") {COUNT.times{ a.take(a.size) }}
x.report("a.clone") {COUNT.times{ a.clone }}
x.report("a[0,a.size]"){COUNT.times{ a[0,a.size] }}
end