在python中,n项对列表和[0]*n的不同追加?
我有两个相同的代码在python中,n项对列表和[0]*n的不同追加?,python,Python,我有两个相同的代码 Code1 >>> a=[0]*60000000 Code2 >>> a=[] >>> for i in range(0,60000000): a.append(0) 在我的电脑中,Code1需要的时间是1s,而Code2需要的时间是480s 为什么?有什么不同?在Python 2.7中,range本身创建一个列表,而不是迭代器。因此,您在Code2中的工作要加倍。这意味着,您首先创建一个包含60000
Code1
>>> a=[0]*60000000
Code2
>>> a=[]
>>> for i in range(0,60000000):
a.append(0)
在我的电脑中,Code1
需要的时间是1s,而Code2
需要的时间是480s为什么?有什么不同?
在Python 2.7中,range
本身创建一个列表,而不是迭代器。因此,您在Code2
中的工作要加倍。这意味着,您首先创建一个包含6000000项的列表,然后对其进行迭代<代码>代码1不需要中间步骤
此[range]是一个多功能函数,用于创建包含算术运算的列表
进展
资源:
将其与Python3.x进行比较:
range不是一个函数,而是一个不可变的序列
类型,如范围和序列类型-列表、元组、范围中所述
资料来源:
尝试使用
xrange
而不是range
,然后再次进行测试。忽略使用range
而不是xrange
的事实,有两件事正在发生:
1) 这些函数做的事情并不相同,尽管它们得到的是相同的输出。你的code1
意味着“6000万份[0]
连在一起”。显然,这不是Code2
正在做的事情——它必须调用列表的append
方法6000万次
2) python中的显式循环速度很慢。在Code1
的某个地方有一个循环,但它是以“C速度”出现的,而不是python速度
def f():
a = [0]*6000000
def g():
a = []
for i in xrange(6000000):
a.append(0)
%timeit f()
10 loops, best of 3: 31 ms per loop
%timeit g()
1 loops, best of 3: 358 ms per loop
在这样的紧密循环中,大部分开销都在循环本身,而不是其中包含的操作。因此,优化紧循环的一种流行方法是将它们放入一个理解中:
def h():
[0 for _ in xrange(6000000)]
%timeit h()
10 loops, best of 3: 151 ms per loop
请注意,这两个函数的作用也不相同,这就是为什么f
和h
之间存在差异的原因(在下面的内容中,我假设您使用的是Python 3;在Python 2中,情况类似,但我们必须讨论由于范围
而导致的内存分配成本)
您的第二个程序在Python字节码中运行。让我们使用模块将其拆解:
循环从字节22到41运行,每次循环,Python都必须解码和执行七字节代码指令,并调用一个函数(函数是a.append
)。这是4.2亿字节代码指令和6000万函数调用
而您的第一个程序在本机代码中运行:
您可以看到,不仅没有循环,也没有函数调用。所有工作都发生在二进制乘法指令的“引擎盖下”,该指令发送给,并且由于列表[0]
仅包含一个元素,因此结果在第529–536行的紧密循环中构造:
if(Py_大小(a)==1){
elem=a->ob_项[0];
对于(i=0;i
code1:纯内存初始化;其中,代码2包含2个开销列表-礼貌范围(),不要忘记for loopOK谢谢。但为什么是时候编写代码2了!=2*1码?!创建列表并使用for比在Code1中所做的工作要昂贵得多,尤其是当您考虑到与操作系统内存处理相关的问题时。
>>> import dis
>>> dis.dis('a=[]\nfor i in range(0,60000000):\n a.append(0)')
1 0 BUILD_LIST 0
3 STORE_NAME 0 (a)
2 6 SETUP_LOOP 36 (to 45)
9 LOAD_NAME 1 (range)
12 LOAD_CONST 0 (0)
15 LOAD_CONST 1 (60000000)
18 CALL_FUNCTION 2 (2 positional, 0 keyword pair)
21 GET_ITER
>> 22 FOR_ITER 19 (to 44)
25 STORE_NAME 2 (i)
3 28 LOAD_NAME 0 (a)
31 LOAD_ATTR 3 (append)
34 LOAD_CONST 0 (0)
37 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
40 POP_TOP
41 JUMP_ABSOLUTE 22
>> 44 POP_BLOCK
>> 45 LOAD_CONST 2 (None)
48 RETURN_VALUE
>>> dis.dis('a = [0] * 60000000')
1 0 LOAD_CONST 0 (0)
3 BUILD_LIST 1
6 LOAD_CONST 1 (60000000)
9 BINARY_MULTIPLY
10 STORE_NAME 0 (a)
13 LOAD_CONST 2 (None)
16 RETURN_VALUE