Skuteczne sposoby duplikowania tablicy / listy w Pythonie

Uwaga: Jestem programistą Ruby, który próbuje znaleźć swoją drogę w Pythonie.

Kiedy chciałem dowiedzieć się, dlaczego niektóre skrypty korzystająmylist[:] zamiastlist(mylist) na zduplikowane listy dokonałem szybkiego porównania różnych metod duplikowaniarange(10) (patrz kod poniżej).

EDYTOWAĆ: Zaktualizowałem testy, aby korzystać z Pythonatimeit jak sugerowano poniżej. To uniemożliwia bezpośrednie porównanie go z Ruby, ponieważtimeit nie uwzględnia pętli podczas RubyBenchmark robi, więc kod Ruby jest dlatylko odniesienie.

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

Dla odniesienia napisałem ten sam skrypt także w 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)

Pytanie 1: co jestmylist[:] inaczej niż jest25% szybciej niż nawetmylist[0:len(mylist)]. Czy kopiuje się bezpośrednio do pamięci lub co?

Pytanie 2: edytować: zaktualizowane testy porównawcze nie pokazują już większych różnic w Pythonie i Rubim.było: Czy zaimplementowałem testy w sposób oczywiście nieefektywny, tak że kod Ruby jest o wiele szybszy niż Python?

Teraz listy kodów:

Pyton:

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)

Rubin:

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

questionAnswers(2)

yourAnswerToTheQuestion