编程语言
首页 > 编程语言> > 为什么评估布尔对象需要花费时间在python中

为什么评估布尔对象需要花费时间在python中

作者:互联网

我使用timeit模块比较了这两个代码片段,并意识到第二个代码片段稍快一些:

~$python -m timeit —setup "l=[1, 2];k=1" "l[k==1]"
10000000 loops, best of 3: 0.0414 usec per loop
~$python -m timeit —setup "l=[1, 2];k=1" "l[0 if k==1 else 1]"
10000000 loops, best of 3: 0.0372 usec per loop

由于逻辑是相同的,我认为评估布尔对象比整数等价花费更多的时间(True == 1和False == 0),因此我提出了以下基准测试,结果证明我是正确的:

~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0411 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0394 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[False]"
10000000 loops, best of 3: 0.0416 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0428 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0394 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[True]"
10000000 loops, best of 3: 0.0393 usec per loop
~$
~$
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[0]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop
~$python -m timeit —setup "l=range(1000)" "l[1]"
10000000 loops, best of 3: 0.0232 usec per loop

但我不知道其根本原因是什么.我的意思是为什么评估True和False需要更多时间?在基准测试中我也发现了另一个神秘的事情.在基准测试的第一部分中,结果存在差异,而第二部分的数字是稳定的.

解决方法:

对于l [k == 1]和l [0如果k == 1其他1],你没有足够长的时间.你看到的差异在于你从随机变化中获得的差异.我不确定哪种形式最终更快,但更长的试验显示出相反的效果:

>>> timeit.timeit('l[k==1]', 'l=[1,2];k=1', number=100000000)
10.782931089401245
>>> timeit.timeit('l[0 if k==1 else 1]', 'l=[1,2];k=1', number=100000000)
11.140317916870117

l [0如果k == 1其他1]出乎意料地竞争,因为l [k == 1]没有达到BINARY_SUBSCR操作码的fast path

TARGET_NOARG(BINARY_SUBSCR)
{
    w = POP();
    v = TOP();
    if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
        /* INLINE: list[int] */
        Py_ssize_t i = PyInt_AsSsize_t(w);
        if (i < 0)
            i += PyList_GET_SIZE(v);
        if (i >= 0 && i < PyList_GET_SIZE(v)) {
            x = PyList_GET_ITEM(v, i);
            Py_INCREF(x);
        }
        else
            goto slow_get;
    }
    else
      slow_get:
        x = PyObject_GetItem(v, w);

在你的第二个测试中,还有另一个因素,在Python 2中,True是内置变量查找,而1是更快的LOAD_CONST. LOAD_CONST仅索引到代码对象的co_consts元组中,而内置查找则需要两次dict查找.

标签:python,boolean,internals,performance
来源: https://codeday.me/bug/20190628/1312820.html