我指的是这个问题,特别是对@David Robinson和@mgilson的第一个答案的评论: 在列表中求和每个元组的第二个值
最初的问题是将每个tuble的第二个值相加:
structure = [('a', 1), ('b', 3), ('c', 2)]
Run Code Online (Sandbox Code Playgroud)
第一个答案:
sum(n for _, n in structure)
Run Code Online (Sandbox Code Playgroud)
第二个答案:
sum(x[1] for x in structure)
Run Code Online (Sandbox Code Playgroud)
根据讨论,第一个答案是快50%.
一旦我弄明白第一个答案是什么(来自Perl,我用Google搜索了特殊的_变量意味着在python中),我想知道怎么会出现一个纯粹的子集任务(只获得每个元组的第二个元素与获取和绑定到变量这两个元素)实际上更慢?是否缺少优化Python中的索引访问的机会?我错过了第二个答案需要时间吗?
Mar*_*ers 35
如果你看一下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
Run Code Online (Sandbox Code Playgroud)
元组解包操作是一个简单的字节码(UNPACK_SEQUENCE),而索引操作必须调用元组(BINARY_SUBSCR)上的方法.解包操作可以在内联中在python评估循环中进行,而订阅调用需要在元组对象上查找函数以使用来检索值PyObject_GetItem.
的UNPACK_SEQUENCE操作码的源代码特殊情况下,蟒元组或列表解包,其中所述序列长度的长度参数精确匹配:
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
Run Code Online (Sandbox Code Playgroud)
上面的代码进入元组的本机结构并直接检索值; 不需要使用大量调用,例如PyObject_GetItem必须考虑对象可以是自定义python类.
该BINARY_SUBSCR码只为Python优化列表 ; 任何不是本机python列表的东西都需要PyObject_GetItem调用.
Amb*_*ber 17
索引通过__getitem__特殊方法进行,因此必须对每个项执行函数查找和执行.这意味着,对于n项目列表,您最终会进行n查找/调用.
使用本机列表/元组时,解包不必处理; 它只是通过__iter__一次调用,然后在C中解压缩结果序列.
| 归档时间: |
|
| 查看次数: |
1562 次 |
| 最近记录: |