我的元组如下:
t=(1,2,3,4,5,6)
我希望将其转换为列表,尽管有一种直接的
方式l=list(t)
我想了解以下是否效率更低,如果是这样的话?
l=[*t]
这更像是要了解解包并将其打包回列表中是否有任何与list(tuple)
相关的开销。
我会尝试对两者进行基准测试并在此处发布结果,但如果有人能够提出一些见解,那就太棒了。
答案 0 :(得分:5)
使用timeit和dis模块检查自己非常容易。我把这个脚本打了一遍:
import timeit
import dis
def func(t):
return list(t)
def unpack(t):
return [*t]
def func_wrapper():
t = (1,2,3,4,5,6)
func(t)
def unpack_wrapper():
t = (1,2,3,4,5,6)
unpack(t)
print("Disassembly with function:")
print(dis.dis(func))
print("Dissassembly with unpack:")
print(dis.dis(unpack))
print("Func time:")
print(timeit.timeit(func_wrapper, number=10000))
print("Unpack time:")
print(timeit.timeit(unpack_wrapper, number=10000))
运行它会显示此输出:
Disassembly with function:
5 0 LOAD_GLOBAL 0 (list)
2 LOAD_FAST 0 (t)
4 CALL_FUNCTION 1
6 RETURN_VALUE
None
Dissassembly with unpack:
8 0 LOAD_FAST 0 (t)
2 BUILD_LIST_UNPACK 1
4 RETURN_VALUE
None
Func time:
0.002832347317420137
Unpack time:
0.0016913349487029865
反汇编显示函数方法的反汇编需要通过解包方法进行一次额外的函数调用。时序结果表明,正如预期的那样,函数调用与使用内置运算符的开销会导致执行时间的显着增加。
仅通过执行时间,解包就更“有效”。但请记住,执行时间只是等式的一部分 - 这必须与可读性和某些情况下的内存消耗(更难以进行基准测试)相平衡。在大多数情况下,我建议您坚持使用该功能,因为它更容易阅读。如果频繁执行此代码(如在长时间运行的循环中),我只会切换到解包方法和位于脚本的关键路径上。