在python中制作不可变对象的修改副本的最快方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在python中制作不可变对象的修改副本的最快方法相关的知识,希望对你有一定的参考价值。

如果我有一个存储一些不可变对象(如int)的元组对象,并且我需要尽可能高效/快速地创建这个元组的修改版本,那么最好的方法是什么?

这是我目前拥有的简化示例。

orig_tuple = (1, 0, 0)
new_tuple = (some_function(element) for element in orig_tuple)

这是否快得多?列表理解是否增加了很多开销?

答案

函数调用增加了开销,而不是listcomp。这会返回一个生成器,而不是一个元组,小心它不一样。

另一答案

要对您的想法进行基准测试或分析,请尝试使用内置于Python中的distimeit库。我在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:Usersuser>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是我能想到的最好的另一种方式来做你想做的事情。如果您有任何其他想法,请测试它们并在需要反馈时编辑您的问题。

以上是关于在python中制作不可变对象的修改副本的最快方法的主要内容,如果未能解决你的问题,请参考以下文章

值传递vs引用传递

创建任何对象的只读/不可变副本(包括深层属性)

Python基础_列表元祖和字典

python天坑------可变对象

python可变类型和不可变类型

python 函数传递可变不可变对象