gpt4 book ai didi

python - 为什么 Python 优化了 "if 0"而不是 "if None"?

转载 作者:IT老高 更新时间:2023-10-28 20:55:43 25 4
gpt4 key购买 nike

为什么如果你编译一个像这样的条件表达式

def f():
if None:
print(222)
if 0:
print(333)

使用数字的分支得到优化,但使用 None 的分支没有?示例:

 3        0 LOAD_CONST               0 (None)
3 POP_JUMP_IF_FALSE 14

4 6 LOAD_CONST 1 (222)
9 PRINT_ITEM
10 PRINT_NEWLINE
11 JUMP_FORWARD 0 (to 14)

5 >> 14 LOAD_CONST 0 (None)
17 RETURN_VALUE

if 0if None 在哪些情况下表现不同?

最佳答案

我的猜测:这是一个疏忽,因为 None 只是 python-2.x 中的一个特殊名称(或全局)。

如果您查看 bytecode-optimizer code in python-2.x :

switch (opcode) {

/* ... More cases ... */

/* Replace LOAD_GLOBAL/LOAD_NAME None
with LOAD_CONST None */
case LOAD_NAME:
case LOAD_GLOBAL:
j = GETARG(codestr, i);
name = PyString_AsString(PyTuple_GET_ITEM(names, j));
if (name == NULL || strcmp(name, "None") != 0)
continue;
for (j=0 ; j < PyList_GET_SIZE(consts) ; j++) {
if (PyList_GET_ITEM(consts, j) == Py_None)
break;
}
if (j == PyList_GET_SIZE(consts)) {
if (PyList_Append(consts, Py_None) == -1)
goto exitError;
}
assert(PyList_GET_ITEM(consts, j) == Py_None);
codestr[i] = LOAD_CONST;
SETARG(codestr, i, j);
cumlc = lastlc + 1;
break; /* Here it breaks, so it can't fall through into the next case */

/* Skip over LOAD_CONST trueconst
POP_JUMP_IF_FALSE xx. This improves
"while 1" performance. */
case LOAD_CONST:
cumlc = lastlc + 1;
j = GETARG(codestr, i);
if (codestr[i+3] != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks,i,6) ||
!PyObject_IsTrue(PyList_GET_ITEM(consts, j)))
continue;
memset(codestr+i, NOP, 6);
cumlc = 0;
break;

/* ... More cases ... */

}

您可能会注意到 None 加载了 LOAD_GLOBALLOAD_NAME,然后替换为 LOAD_CONST

但是:在它被替换后它是 breaks,所以它不能进入​​ LOAD_CONST block 将被替换为 NOP 的情况 如果常量不是 True


在 python-3.x 中,优化器不需要对名称(或全局)None 进行特殊处理,因为它总是加载有 LOAD_CONSTbytecode-optimizer reads :

switch (opcode) {

/* ... More cases ... */

/* Skip over LOAD_CONST trueconst
POP_JUMP_IF_FALSE xx. This improves
"while 1" performance. */
case LOAD_CONST:
CONST_STACK_PUSH_OP(i);
if (nextop != POP_JUMP_IF_FALSE ||
!ISBASICBLOCK(blocks, op_start, i + 1) ||
!PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
break;
fill_nops(codestr, op_start, nexti + 1);
CONST_STACK_POP(1);
break;

/* ... More cases ... */

}

LOAD_NAMELOAD_GLOBAL 没有特殊情况了,所以 if None (还有 if False - False 在 python-3.x 中也被设为常量)将进入 LOAD_CONST 情况,然后被 NOP 替换。

关于python - 为什么 Python 优化了 "if 0"而不是 "if None"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44389850/

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