gpt4 book ai didi

python - 元组比 Python 中的列表更有效吗?

转载 作者:IT老高 更新时间:2023-10-28 12:19:11 24 4
gpt4 key购买 nike

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

最佳答案

总结

在几乎所有类别中,元组的性能往往都优于列表:

  1. 元组可以是constant folded .

  2. 元组可以重复使用而不是复制。

  3. 元组是紧凑的,不会过度分配。

  4. 元组直接引用它们的元素。

元组可以不断折叠

常量元组可以由 Python 的窥视孔优化器或 AST 优化器预先计算。另一方面,列表是从头开始构建的:

    >>> from dis import dis

>>> dis(compile("(10, 'abc')", '', 'eval'))
1 0 LOAD_CONST 2 ((10, 'abc'))
3 RETURN_VALUE

>>> dis(compile("[10, 'abc']", '', 'eval'))
1 0 LOAD_CONST 0 (10)
3 LOAD_CONST 1 ('abc')
6 BUILD_LIST 2
9 RETURN_VALUE

元组不需要复制

运行 tuple(some_tuple) 立即返回自身。由于元组是不可变的,因此不必复制它们:

>>> a = (10, 20, 30)
>>> b = tuple(a)
>>> a is b
True

相比之下,list(some_list) 要求将所有数据复制到一个新列表中:

>>> a = [10, 20, 30]
>>> b = list(a)
>>> a is b
False

元组不会过度分配

由于元组的大小是固定的,它可以比需要过度分配以提高 append() 操作效率的列表更紧凑地存储。

这给元组一个很好的空间优势:

>>> import sys
>>> sys.getsizeof(tuple(iter(range(10))))
128
>>> sys.getsizeof(list(iter(range(10))))
200

这是来自 Objects/listobject.c 的注释,它解释了列表的作用:

/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
* Note: new_allocated won't overflow because the largest possible value
* is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
*/

元组直接引用它们的元素

对对象的引用直接合并到元组对象中。相比之下,列表对外部指针数组有一个额外的间接层。

这使元组在索引查找和解包方面具有较小的速度优势:

$ python3.6 -m timeit -s 'a = (10, 20, 30)' 'a[1]'
10000000 loops, best of 3: 0.0304 usec per loop
$ python3.6 -m timeit -s 'a = [10, 20, 30]' 'a[1]'
10000000 loops, best of 3: 0.0309 usec per loop

$ python3.6 -m timeit -s 'a = (10, 20, 30)' 'x, y, z = a'
10000000 loops, best of 3: 0.0249 usec per loop
$ python3.6 -m timeit -s 'a = [10, 20, 30]' 'x, y, z = a'
10000000 loops, best of 3: 0.0251 usec per loop

Here元组 (10, 20) 是如何存储的:

    typedef struct {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
Py_ssize_t ob_size;
PyObject *ob_item[2]; /* store a pointer to 10 and a pointer to 20 */
} PyTupleObject;

Here是列表 [10, 20] 的存储方式:

    PyObject arr[2];              /* store a pointer to 10 and a pointer to 20 */

typedef struct {
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
Py_ssize_t ob_size;
PyObject **ob_item = arr; /* store a pointer to the two-pointer array */
Py_ssize_t allocated;
} PyListObject;

请注意,元组对象直接合并了两个数据指针,而列表对象对保存两个数据指针的外部数组有一个额外的间接层。

关于python - 元组比 Python 中的列表更有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com