1

在 Python 中,有时我想做类似 (1) 的事情

if __debug__ and verbose: print "whatever"

如果 Python 使用 -O 运行,那么我希望整段代码消失,就像我只有 (2)

if __debug__: print "whatever"

甚至 (3)

if __debug__:
    if verbose: print foo

但是,这似乎没有发生(见下文)。有没有一种方法可以让 #3 的运行时效率更接近 #1 的紧凑代码?

以下是我测试我没有得到我想要的高效代码的方法:

#!/usr/bin/python2.7

from dis import dis
import sys

cmds = ["""
def func ():
    if __debug__ and 1+1: sys.stdout.write('spam')""",   """
def func():
    if __debug__: sys.stdout.write('ham')""",     """
def func():
    __debug__ and sys.stdout.write('eggs')"""]

print "__debug__ is", __debug__, "\n\n\n"

for cmd in cmds:
    print "*"*80, "\nSource of {}\n\ncompiles to:".format(cmd)
    exec(cmd)
    dis(func)
    print "\n"*4

运行这个给出

__debug__ is False 



******************************************************************************** 
Source of 
def func ():
    if __debug__ and 1+1: sys.stdout.write('spam')

compiles to:
  3           0 LOAD_GLOBAL              0 (__debug__)
              3 POP_JUMP_IF_FALSE       31
              6 LOAD_CONST               3 (2)
              9 POP_JUMP_IF_FALSE       31
             12 LOAD_GLOBAL              1 (sys)
             15 LOAD_ATTR                2 (stdout)
             18 LOAD_ATTR                3 (write)
             21 LOAD_CONST               2 ('spam')
             24 CALL_FUNCTION            1
             27 POP_TOP             
             28 JUMP_FORWARD             0 (to 31)
        >>   31 LOAD_CONST               0 (None)
             34 RETURN_VALUE        





******************************************************************************** 
Source of 
def func():
    if __debug__: sys.stdout.write('ham')

compiles to:
  3           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE        





******************************************************************************** 
Source of 
def func():
    __debug__ and sys.stdout.write('eggs')

compiles to:
  3           0 LOAD_GLOBAL              0 (__debug__)
              3 JUMP_IF_FALSE_OR_POP    21
              6 LOAD_GLOBAL              1 (sys)
              9 LOAD_ATTR                2 (stdout)
             12 LOAD_ATTR                3 (write)
             15 LOAD_CONST               1 ('eggs')
             18 CALL_FUNCTION            1
        >>   21 POP_TOP             
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE        
4

1 回答 1

5

不,你不能。Python 的编译器不够智能,无法检测在什么情况下它可以删除代码块和if语句。

否则,Python 将不得不进行大量的逻辑推理。比较:

if __debug__ or verbose:

if __debug__ and verbose:

例如。Python 必须在编译时检测这两个表达式之间的差异;一个可以优化掉,另一个不能。

请注意,有和没有语句的代码在运行时的差异if __debug__确实很小,其他一切都相同。一个小的常数值测试和跳跃真的没什么好大惊小怪的。

于 2013-07-10T20:02:52.440 回答