为什么在Python中使用[e]*n(用于创建重复n次的单个项的列表)速度很快?
后续行动来自: 显然,由于距离的原因,第二个速度较慢。我不知道[e]*n为什么这么快,也不知道它是如何在Python内部实现的。让您了解Python在计算每个表达式时执行的操作:为什么在Python中使用[e]*n(用于创建重复n次的单个项的列表)速度很快?,python,list,Python,List,后续行动来自: 显然,由于距离的原因,第二个速度较慢。我不知道[e]*n为什么这么快,也不知道它是如何在Python内部实现的。让您了解Python在计算每个表达式时执行的操作: In [57]: dis.dis(lambda: [0.5]*100000) 1 0 LOAD_CONST 1 (0.5) 3 BUILD_LIST 1 6 LOAD_CONST
In [57]: dis.dis(lambda: [0.5]*100000)
1 0 LOAD_CONST 1 (0.5)
3 BUILD_LIST 1
6 LOAD_CONST 2 (100000)
9 BINARY_MULTIPLY
10 RETURN_VALUE
In [58]: dis.dis(lambda: [0.5 for i in range(100000)])
1 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (100000)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (i)
19 LOAD_CONST 2 (0.5)
22 LIST_APPEND 2
25 JUMP_ABSOLUTE 13
>> 28 RETURN_VALUE
列表理解是执行循环,每次加载常量0.5,并将其附加到结果列表
表达式[0.5]*100000只需要一个
还要注意的是,[obj]*N列出了长度N,其中N表示完全相同的obj
列表理解[expr for i in range N]计算expr N次,即使每次expr的计算结果都相同。让您可以查看Python在计算每个表达式时执行的操作:
In [57]: dis.dis(lambda: [0.5]*100000)
1 0 LOAD_CONST 1 (0.5)
3 BUILD_LIST 1
6 LOAD_CONST 2 (100000)
9 BINARY_MULTIPLY
10 RETURN_VALUE
In [58]: dis.dis(lambda: [0.5 for i in range(100000)])
1 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (100000)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (i)
19 LOAD_CONST 2 (0.5)
22 LIST_APPEND 2
25 JUMP_ABSOLUTE 13
>> 28 RETURN_VALUE
列表理解是执行循环,每次加载常量0.5,并将其附加到结果列表
表达式[0.5]*100000只需要一个
还要注意的是,[obj]*N列出了长度N,其中N表示完全相同的obj
列表理解[expr for i in range N]计算expr N次-即使每次expr的计算结果都相同。再加上@unutbu所说的,二进制乘法最终执行以下紧循环: 这是非常不言自明的:它在一个紧凑的C循环中对同一个对象进行了大量引用。因此,几乎100%的[obj]*N在本机代码中执行,这意味着它运行得非常快
关于对可变对象执行此操作的标准警告适用于ie:不要对可变对象执行此操作,因为您对同一对象进行了大量引用。再加上@unutbu所说的,二进制乘法最终会执行以下紧循环: 这是非常不言自明的:它在一个紧凑的C循环中对同一个对象进行了大量引用。因此,几乎100%的[obj]*N在本机代码中执行,这意味着它运行得非常快
对可变对象执行此操作的标准警告适用于ie:不要对可变对象执行此操作,因为您对同一对象进行了大量引用。因为在CPython中,分配和复制PyObject*在C中很快?我不确定你想要的是什么样的答案…?问题是什么?我做了一些编辑。因为在CPython中,分配和复制PyObject*在C中很快?我不确定你想要什么样的答案…?问题是什么?我做了一些编辑。
if (Py_SIZE(a) == 1) {
elem = a->ob_item[0];
for (i = 0; i < n; i++) {
items[i] = elem;
Py_INCREF(elem);
}
return (PyObject *) np;
}