gpt4 book ai didi

python - 在 Python 中复制数组/列表的有效方法

转载 作者:太空狗 更新时间:2023-10-29 20:46:06 25 4
gpt4 key购买 nike

注意:我是一名 Ruby 开发人员,正试图在 Python 中找到自己的出路。

当我想弄清楚为什么有些脚本使用 mylist[:] 而不是 list(mylist) 来复制列表时,我对各种方法做了一个快速基准测试复制 range(10)(见下面的代码)。

编辑:我更新了测试以使用 Python 的 timeit,如下所示。这使得无法直接将它与 Ruby 进行比较,因为 timeit 没有考虑循环,而 Ruby 的 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[:] 的不同之处在于它比 mylist[0: 快 25% len(我的列表)]。它是直接复制到内存中还是什么?

问题 2:编辑:更新的基准测试不再显示 Python 和 Ruby 的巨大差异。 是:我是否以某种明显低效的方式实现测试,以至于 Ruby 代码比 Python 快得多?

现在是代码 list :

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)

ruby :

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

最佳答案

使用 timeit用于测试时序的 Python 模块。

from copy import *

a=range(1000)

def cop():
b=copy(a)

def func1():
b=list(a)

def slice():
b=a[:]

def slice_len():
b=a[0:len(a)]



if __name__=="__main__":
import timeit
print "copy(a)",timeit.timeit("cop()", setup="from __main__ import cop")
print "list(a)",timeit.timeit("func1()", setup="from __main__ import func1")
print "a[:]",timeit.timeit("slice()", setup="from __main__ import slice")
print "a[0:len(a)]",timeit.timeit("slice_len()", setup="from __main__ import slice_len")

结果:

copy(a) 3.98940896988
list(a) 2.54542589188
a[:] 1.96630120277 #winner
a[0:len(a)] 10.5431251526

肯定是 a[0:len(a)] 中涉及的额外步骤是它缓慢的原因。

下面是两者的字节码对比:

In [19]: dis.dis(func1)
2 0 LOAD_GLOBAL 0 (range)
3 LOAD_CONST 1 (100000)
6 CALL_FUNCTION 1
9 STORE_FAST 0 (a)

3 12 LOAD_FAST 0 (a)
15 SLICE+0
16 STORE_FAST 1 (b)
19 LOAD_CONST 0 (None)
22 RETURN_VALUE

In [20]: dis.dis(func2)
2 0 LOAD_GLOBAL 0 (range)
3 LOAD_CONST 1 (100000)
6 CALL_FUNCTION 1
9 STORE_FAST 0 (a)

3 12 LOAD_FAST 0 (a) #same up to here
15 LOAD_CONST 2 (0) #loads 0
18 LOAD_GLOBAL 1 (len) # loads the builtin len(),
# so it might take some lookup time
21 LOAD_FAST 0 (a)
24 CALL_FUNCTION 1
27 SLICE+3
28 STORE_FAST 1 (b)
31 LOAD_CONST 0 (None)
34 RETURN_VALUE

关于python - 在 Python 中复制数组/列表的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13047895/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com