use*_*619 10 python list-comprehension
我试图找到列表理解的效率,但它看起来比正常的功能操作更昂贵.谁能解释一下?
def squares(values):
lst = []
for x in range(values):
lst.append(x*x)
return lst
def main():
t = timeit.Timer(stmt="lst = [x*x for x in range(10)]")
print t.timeit()
t = timeit.Timer(stmt="squares",setup="from __main__ import squares")
print t.timeit()
lst = [x*x for x in range(10)]
print lst
print squares(10)
----Output:---
2.4147507644
0.0284455255965
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Run Code Online (Sandbox Code Playgroud)
对于相同的输出,与列表理解相比,正常函数在非常短的时间内计算.
我认为列表理解更有效.
Mar*_*ers 36
你永远不会调用你的squares函数,因此它没有做任何事情.
List内涵是实际上更快:
>>> import timeit
>>> def squares(values):
... lst = []
... for x in range(values):
... lst.append(x*x)
... return lst
...
>>> def squares_comp(values):
... return [x*x for x in range(values)]
...
>>> timeit.timeit('f(10)', 'from __main__ import squares as f')
3.9415171146392822
>>> timeit.timeit('f(10)', 'from __main__ import squares_comp as f')
2.3243820667266846
Run Code Online (Sandbox Code Playgroud)
如果您使用该dis模块查看每个函数的字节码,您可以看到原因:
>>> import dis
>>> dis.dis(squares)
2 0 BUILD_LIST 0
3 STORE_FAST 1 (lst)
3 6 SETUP_LOOP 37 (to 46)
9 LOAD_GLOBAL 0 (range)
12 LOAD_FAST 0 (values)
15 CALL_FUNCTION 1
18 GET_ITER
>> 19 FOR_ITER 23 (to 45)
22 STORE_FAST 2 (x)
4 25 LOAD_FAST 1 (lst)
28 LOAD_ATTR 1 (append)
31 LOAD_FAST 2 (x)
34 LOAD_FAST 2 (x)
37 BINARY_MULTIPLY
38 CALL_FUNCTION 1
41 POP_TOP
42 JUMP_ABSOLUTE 19
>> 45 POP_BLOCK
5 >> 46 LOAD_FAST 1 (lst)
49 RETURN_VALUE
>>> dis.dis(squares_comp)
2 0 BUILD_LIST 0
3 LOAD_GLOBAL 0 (range)
6 LOAD_FAST 0 (values)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 16 (to 32)
16 STORE_FAST 1 (x)
19 LOAD_FAST 1 (x)
22 LOAD_FAST 1 (x)
25 BINARY_MULTIPLY
26 LIST_APPEND 2
29 JUMP_ABSOLUTE 13
>> 32 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
该squares函数.append()在每次迭代中查找列表的方法,并调用它.该.append()函数每次调用时都必须将列表增加一个元素.
另一方面,列表理解不一定要做那项工作.相反,python使用LIST_APPEND字节码,它使用C API将新元素附加到列表中,而不必执行查找和对函数的python调用.
| 归档时间: |
|
| 查看次数: |
2159 次 |
| 最近记录: |