元组是否比Python中的列表更有效?

时间:2020-03-05 18:54:58  来源:igfitidea点击:

在元素的实例化和检索方面,元组和列表之间是否存在性能差异?

解决方案

回答

元组应该比列表稍有效率,因此比列表更快,因为它们是不可变的。

回答

通常,我们可能期望元组会稍微快一些。但是,我们一定要测试特定情况(如果差异可能会影响程序的性能,请记住"过早的优化是万恶之源")。

Python非常简单:timeit是朋友。

$ python -m timeit "x=(1,2,3,4,5,6,7,8)"
10000000 loops, best of 3: 0.0388 usec per loop

$ python -m timeit "x=[1,2,3,4,5,6,7,8]"
1000000 loops, best of 3: 0.363 usec per loop

和...

$ python -m timeit -s "x=(1,2,3,4,5,6,7,8)" "y=x[3]"
10000000 loops, best of 3: 0.0938 usec per loop

$ python -m timeit -s "x=[1,2,3,4,5,6,7,8]" "y=x[3]"
10000000 loops, best of 3: 0.0649 usec per loop

因此,在这种情况下,元组的实例化速度几乎快一个数量级,但列表的项目访问实际上要快一些!因此,如果要创建一些元组并多次访问它们,则实际上使用列表可能会更快。

当然,如果我们要更改一项,则列表肯定会更快,因为我们需要创建一个完整的新元组来更改一项(因为元组是不可变的)。

回答

dis模块反汇编一个函数的字节码,对于查看元组和列表之间的区别很有用。

在这种情况下,我们可以看到访问元素会生成相同的代码,但是分配元组要比分配列表快得多。

>>> def a():
...     x=[1,2,3,4,5]
...     y=x[2]
...
>>> def b():
...     x=(1,2,3,4,5)
...     y=x[2]
...
>>> import dis
>>> dis.dis(a)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 LOAD_CONST               4 (4)
             12 LOAD_CONST               5 (5)
             15 BUILD_LIST               5
             18 STORE_FAST               0 (x)

  3          21 LOAD_FAST                0 (x)
             24 LOAD_CONST               2 (2)
             27 BINARY_SUBSCR
             28 STORE_FAST               1 (y)
             31 LOAD_CONST               0 (None)
             34 RETURN_VALUE
>>> dis.dis(b)
  2           0 LOAD_CONST               6 ((1, 2, 3, 4, 5))
              3 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              9 LOAD_CONST               2 (2)
             12 BINARY_SUBSCR
             13 STORE_FAST               1 (y)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

回答

元组是不可变的,具有更高的内存效率;为了提高效率,列表列出了整体内存,以允许没有常量realloc的追加。因此,如果要遍历代码中恒定的值序列(例如,"向上","右侧","向下","左侧"的方向),则首选元组,因为此类元组是预-在编译时计算。

访问速度应该相同(它们都作为连续数组存储在内存中)。

但是,当我们处理可变数据时," alist.append(item)"比" atuple + =(item,)"更受青睐。请记住,元组应被视为没有字段名称的记录。

回答

如果列表或者元组中的所有项目都属于同一类型,则还应该考虑标准库中的"数组"模块。它可以更快并且占用更少的内存。