如果我有一个存储一些不可变对象(如int)的元组对象,并且我需要尽可能高效/快速地创建这个元组的修改版本,那么最好的方法是什么?
这是我目前拥有的简化示例。
orig_tuple = (1, 0, 0)
new_tuple = (some_function(element) for element in orig_tuple)
这是否快得多?列表理解是否增加了很多开销?
函数调用增加了开销,而不是listcomp。这会返回一个生成器,而不是一个元组,小心它不一样。
要对您的想法进行基准测试或分析,请尝试使用内置于Python中的dis
和timeit
库。我在Windows 7 x64上使用Python 2.7
。
import copy
import dis
import timeit
def method_one():
def add_one(i):
return i+1
orig_tuple = (1, 0, 0)
new_tuple = (add_one(element) for element in orig_tuple)
def method_two():
def add_one(i):
return i+1
orig_tuple = (1, 0, 0)
new_tuple = copy.deepcopy(orig_tuple)
for i in new_tuple:
i = add_one(i)
print dis.dis(method_one)
print timeit.timeit(method_one, number=10000)
print dis.dis(method_two)
print timeit.timeit(method_two, number=10000)
制作:
D:\Users\user>python help.py
6 0 LOAD_CONST 1 (<code object add_one at 01DA6B60, file "help.py", line 6
>)
3 MAKE_FUNCTION 0
6 STORE_DEREF 0 (add_one)
9 9 LOAD_CONST 5 ((1, 0, 0))
12 STORE_FAST 0 (orig_tuple)
10 15 LOAD_CLOSURE 0 (add_one)
18 BUILD_TUPLE 1
21 LOAD_CONST 4 (<code object <genexpr> at 01DA6CC8, file "help.py", line
10>)
24 MAKE_CLOSURE 0
27 LOAD_FAST 0 (orig_tuple)
30 GET_ITER
31 CALL_FUNCTION 1
34 STORE_FAST 1 (new_tuple)
37 LOAD_CONST 0 (None)
40 RETURN_VALUE
None
0.0088386
13 0 LOAD_CONST 1 (<code object add_one at 020C6F50, file "help.py", line 1
3>)
3 MAKE_FUNCTION 0
6 STORE_FAST 0 (add_one)
16 9 LOAD_CONST 4 ((1, 0, 0))
12 STORE_FAST 1 (orig_tuple)
17 15 LOAD_GLOBAL 0 (copy)
18 LOAD_ATTR 1 (deepcopy)
21 LOAD_FAST 1 (orig_tuple)
24 CALL_FUNCTION 1
27 STORE_FAST 2 (new_tuple)
18 30 SETUP_LOOP 26 (to 59)
33 LOAD_FAST 2 (new_tuple)
36 GET_ITER
>> 37 FOR_ITER 18 (to 58)
40 STORE_FAST 3 (i)
19 43 LOAD_FAST 0 (add_one)
46 LOAD_FAST 3 (i)
49 CALL_FUNCTION 1
52 STORE_FAST 3 (i)
55 JUMP_ABSOLUTE 37
>> 58 POP_BLOCK
>> 59 LOAD_CONST 0 (None)
62 RETURN_VALUE
None
0.1026118
如您所见,看起来创建该生成器要快得多。 method_two
是我能想到的最好的另一种方式来做你想做的事情。如果您有任何其他想法,请测试它们并在需要反馈时编辑您的问题。