为什么要编译像
这样的条件表达式Button {
width: 100
text: 'Very very long button description.'
Component.onCompleted: contentItem.wrapMode = Text.WordWrap
}
使用数字的分支会被优化,但那些使用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
在哪些情况下表现不同?
答案 0 :(得分:8)
我的猜测:这是一个疏忽,因为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_GLOBAL
或LOAD_NAME
,然后被LOAD_CONST
替换。
但是:在将break
替换为LOAD_CONST
之后,如果常量为'n',则不能进入NOP
情况,在该情况下,块将被替换为True
t None
。
在python-3.x中,优化器不需要特殊情况下的名称(或全局)LOAD_CONST
,因为它总是加载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 ... */
}
和bytecode-optimizer reads:
LOAD_NAME
LOAD_GLOBAL
和if None
不再有特殊情况,因此if False
(但False
- LOAD_CONST
也在python-3中成为常量。 x)将进入NOP
案例,然后由# server.R
function(input, output) {
output$make_box <- renderUI({
checkboxInput("checkbox", label = "Choice A", value = setboxon())
})
setboxon <- eventReactive(input$action, {
if(is.null(input$checkbox))
return(FALSE)
else if(input$checkbox==TRUE)
return(FALSE)
else
return(TRUE)
})
# check status off checkbox value
output$value <- renderPrint({ input$checkbox })
}
替换。
答案 1 :(得分:1)
免责声明:这不是一个真正的答案,而只是我的成功报告 尝试覆盖CPython 2.7中的
None
尽管受到了保护 编译器。
我在CPython 2.7中找到了一种覆盖None
的方法,虽然它涉及一个肮脏的技巧,并且可以类似地对文字进行。即,我替换代码对象的co_consts
字段中的常量条目#0:
def makeNoneTrueIn(func):
c = func.__code__
func.__code__ = type(c)(c.co_argcount,
c.co_nlocals,
c.co_stacksize,
c.co_flags,
c.co_code,
(True, ) + c.co_consts[1:],
c.co_names,
c.co_varnames,
c.co_filename,
c.co_name,
c.co_firstlineno,
c.co_lnotab,
c.co_freevars,
c.co_cellvars)
def foo():
if None:
print "None is true"
else:
print "None is false"
foo()
makeNoneTrueIn(foo)
foo()
输出:
None is false
None is true