Maneras eficientes de duplicar la matriz / lista en Python
Nota: soy un desarrollador de Ruby que trata de encontrar mi camino en Python.
Cuando quise averiguar por qué algunos scripts usanmylist[:]
en lugar delist(mylist)
para duplicar listas, hice un rápido punto de referencia de los diversos métodos para duplicarrange(10)
(ver código abajo).
EDITAR: Actualicé las pruebas para hacer uso de Python.timeit
como se sugiere a continuación. Esto hace que sea imposible compararlo directamente con Ruby, porquecronométralo no tiene en cuenta el bucle mientras que RubyBenchmark
lo hace, por lo que el código de Ruby es parasolo referencia.
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
Para referencia, escribí el mismo script en Ruby también:
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)
Pregunta 1: que esmylist[:]
haciendo diferente que es25% más rápido que inclusomylist[0:len(mylist)]
. ¿Se copia directamente en la memoria o qué?
Pregunta 2: editar: Los puntos de referencia actualizados ya no muestran grandes diferencias en Python y Ruby.estaba: ¿Implementé las pruebas de una manera obviamente ineficiente, de modo que el código Ruby sea mucho más rápido que Python?
Ahora los listados de código:
Pitón:
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)
Rubí:
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