Ответ 1
Мое предположение: это надзор, который произошел, потому что None
является просто специальным именем (или глобальным) в python-2.x.
Если вы посмотрите на код байт-кода-оптимизатора в 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 читает:
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
- False
также была сделана константа в python-3.x) войдет в случай LOAD_CONST
а затем заменить на NOP
.