gpt4 book ai didi

python - 为什么解包比通过索引访问更快?

转载 作者:IT老高 更新时间:2023-10-28 21:51:36 32 4
gpt4 key购买 nike

我指的是这个问题,尤其是@David Robinson 和@mgilson 对第一个答案的评论: Sum the second value of each tuple in a list

最初的问题是对每个 tuble 的第二个值求和:

structure = [('a', 1), ('b', 3), ('c', 2)]

第一个答案:

sum(n for _, n in structure)

第二个答案:

sum(x[1] for x in structure)

根据讨论,第一个答案要快 50%。

一旦我弄清楚第一个答案是做什么的(来自 Perl,我用谷歌搜索了 python 中特殊的 _ 变量的含义),我想知道为什么会出现一个纯子集任务(只获取每个元组的第二个元素与获取和绑定(bind)到变量这两个元素)实际上更慢?是否错过了在 Python 中优化索引访问的机会?我错过了第二个答案需要时间的东西吗?

最佳答案

如果你看一下 python 字节码,你很快就会明白为什么解包速度更快:

>>> import dis
>>> def unpack_or_index(t=(0, 1)):
... _, x = t
... x = t[1]
...
>>> dis.dis(unpack_or_index)
2 0 LOAD_FAST 0 (t)
3 UNPACK_SEQUENCE 2
6 STORE_FAST 1 (_)
9 STORE_FAST 2 (x)

3 12 LOAD_FAST 0 (t)
15 LOAD_CONST 1 (1)
18 BINARY_SUBSCR
19 STORE_FAST 2 (x)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE

元组解包操作是一个简单的字节码(UNPACK_SEQUENCE),而索引操作必须调用元组上的方法(BINARY_SUBSCR)。解包操作可以在 python 评估循环中内联发生,而订阅调用需要在元组对象上查找函数以检索值,使用 PyObject_GetItem

UNPACK_SEQUENCE opcode source code序列长度与参数长度完全匹配的python元组或列表解包的特殊情况:

        if (PyTuple_CheckExact(v) &&
PyTuple_GET_SIZE(v) == oparg) {
PyObject **items = \
((PyTupleObject *)v)->ob_item;
while (oparg--) {
w = items[oparg];
Py_INCREF(w);
PUSH(w);
}
Py_DECREF(v);
continue;
} // followed by an "else if" statement for a list with similar code

上述代码进入元组的原生结构并直接检索值;无需使用诸如 PyObject_GetItem 之类的繁重调用,这些调用必须考虑到对象可能是自定义 python 类。

BINARY_SUBSCR opcode仅针对 python lists 进行了优化;任何不是原生 python 列表的东西都需要 PyObject_GetItem 调用。

关于python - 为什么解包比通过索引访问更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13024416/

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