注意:我是一名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编写了相同的脚本:
红宝石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快得多?
现在的代码清单:
蟒蛇:
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
使用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中旋转列表的最有效方法是什么?现在我有这样的事情: 有没有更好的办法? 问题答案: 已针对两端的推拉进行了优化。他们甚至有专门的方法。
我不是本地JAVA程序员。我正在为web服务API创建一个客户端。API基本上需要一个数组参数。 我正在解析一个XML文件,创建记录,然后使用此API进行批量插入。 问题是这个API一次只能插入200条记录,这意味着我的数组在调用时只能有200条或更少的记录。 由于我不知道预先有多少条记录,所以我将我的记录存储在ArrayList中,然后使用将其转换为Array。ToArray() 现在,由于AP
问题内容: 我想复制一个2D列表,以便如果我修改一个列表,则不修改另一个列表。 对于一维列表,我只是这样做: 现在,如果我修改了b,a就不会修改。 但这不适用于二维列表: 如果我修改了b,a也会被修改。 我该如何解决? 问题答案: 对于不管尺寸多少都可以工作的更通用的解决方案,请使用:
问题内容: 我已经开发了像这样的数组列表 现在我的问题是:如果我想从列表中删除“ 8”,哪种方法更好? 第一种方式: 第二种方式: 现在,请从性能的角度建议其中哪一个效率更高,速度更快,并且还有其他任何类似于内置函数的方法,通过使用它,我们可以删除重复项而无需进行过多迭代。 问题答案: 在性能方面,它们应该相似。你测试了吗 如果要使用内置方法,则可以达到类似的性能(通过测试确认): 最后,如果您想
我需要从一个列表中追加一些重复的值到一个子列表中,让我用一个例子来解释: 我有一个名为的变量,它包含大写字母字符串和符号。 我的最终目标是拥有这个数组: 在示例中,我需要将所有的符号分组到原始中的子列表中,我想过在数组中迭代,找到当前附近的所有符号,然后创建第二个数组,但我想也许还有更多的pythonic我可以做的,有什么想法吗?
问题内容: 我正在寻找一种类似于R函数的高效方法来计算Python中列表的秩向量。在一个简单的列表与所述元件之间没有联系,元件 我 的列表的秩矢量的应该是 X 当且仅当是 X 个在排序的列表元素。到目前为止,这很简单,以下代码片段可以解决问题: 但是,如果原始列表具有联系(即,多个具有相同值的元素),事情就会变得复杂。在这种情况下,所有具有相同值的元素都应具有相同的等级,这是使用上述朴素方法获得的
问题内容: 我在与OS无关的文件管理器中工作,并且正在寻找为Linux复制文件的最有效方法。Windows有一个内置函数CopyFileEx(),但是据我所知,Linux没有这种标准函数。所以我想我将必须实现自己的。明显的方法是fopen / fread / fwrite,但是是否有更好(更快)的方法呢?我还必须有能力每隔一段时间停止一次,以便可以更新文件进度菜单的“到目前为止”。 问题答案: 不
问题内容: 我希望编写一个提供JSON对象列表的Web服务。返回以下内容的JSON是否有效: 还是将其放在单个对象中以返回的“正确”方法: 问题答案: 两种形式均有效。但是,对于API,我建议使用第二种形式。原因是它为您提供扩展API的途径。 例如,如果您有一个返回用户对象数组的API ,后来又决定要包含一些有关返回用户的汇总统计信息,那么没有不破坏现有客户端(或包括每个用户对象中有很多冗余数据)