为什么你编译一个像这样的条件表达式
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 0
和if None
的行为会有所不同?
发布于 2017-06-06 22:31:02
我的猜测是:这是一个疏忽,因为在None
-2.x中,python只是一个特殊大小写的名称(或全局名称)。
如果你看一下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_GLOBAL
或LOAD_NAME
加载的,然后用LOAD_CONST
替换。
但是:在它被替换之后,它会break
s,所以它不能进入LOAD_CONST
的情况,在这种情况下,如果常量不是NOP
,那么这个块就会被True
替换。
在python-3.x中,优化器不需要特殊设置名称(或全局) None
的大小写,因为它总是与LOAD_CONST
和bytecode-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_NAME
和LOAD_GLOBAL
不再有特殊情况,因此if None
(但在if False
-3.x中也将if False
- False
设为常量)将进入LOAD_CONST
情况,然后由NOP
替换。
https://stackoverflow.com/questions/44389850
复制相似问题