3

It seems like python (2.6) is not able to optimize this simple temp variable 'a' ?

I use to assign a local variable to some code in order to reduce the line length.

To me this is a simple optimization any correct compiler can do automatically.

from dis import dis

def f(func):
  func()

def functioncall():
  print ' => function called'

def unoptimized():
  print 'in unoptimized'
  a = functioncall
  f(func=a)

def optimized():
  print 'in optimized'
  f(func=functioncall)

unoptimized()
optimized()

print 'dis(unoptimized)'
dis(unoptimized)
print 'dis(optimized)'
dis(optimized)

Output :

in unoptimized
 => function called
in optimized
 => function called
dis(unoptimized)
 10           0 LOAD_CONST               1 ('in unoptimized')
              3 PRINT_ITEM
              4 PRINT_NEWLINE

 11           5 LOAD_GLOBAL              0 (functioncall)
              8 STORE_FAST               0 (a)

 12          11 LOAD_GLOBAL              1 (f)
             14 LOAD_CONST               2 ('func')
             17 LOAD_FAST                0 (a)
             20 CALL_FUNCTION          256
             23 POP_TOP
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE
dis(optimized)
 15           0 LOAD_CONST               1 ('in optimized')
              3 PRINT_ITEM
              4 PRINT_NEWLINE

 16           5 LOAD_GLOBAL              0 (f)
              8 LOAD_CONST               2 ('func')
             11 LOAD_GLOBAL              1 (functioncall)
             14 CALL_FUNCTION          256
             17 POP_TOP
             18 LOAD_CONST               0 (None)
             21 RETURN_VALUE

Why it cannot remove this automatically?

 11           5 LOAD_GLOBAL              0 (functioncall)
              8 STORE_FAST               0 (a)
4

4 回答 4

5

CPython,Python 的标准实现,没有做太多优化;它是源代码到字节码的非常简单的翻译。有一些优化(消除或提升if __debug__作为其中之一的代码),我确实相信存在某种类型的窥孔优化器,但我认为编译阶段应该相当快,这排除了做很多分析。

可维护性似乎也是核心 Python 开发人员的关键。这是2009 年的一个线程,其中考虑了删除死代码的补丁,然后被拒绝,因为它会使编译器的可维护性降低。

如果你想要高性能,你想要 CPython 以外的东西;也许 PyPy 会有所帮助。Python 通常经过优化以节省程序员的时间,而不是运行时。如果您不希望字节码中有死代码,请不要将其放入源代码中。:-)

于 2013-09-24T15:20:10.060 回答
1

原则上,Python 解释器可以对此进行优化。

在实践中,人们用 Python 编程是因为用它编写代码很快,而不是因为用它编写的代码很快。所以在这种特殊情况下,程序员应该进行优化。

于 2013-09-24T15:20:49.250 回答
0

在 python 中,您的源代码不会完全消失 -def语句是创建函数对象的可执行语句。您在问为什么 python 不聪明地做一些事情,而不是以优化的名义提出的要求。

这种优化很容易手动执行,必要时可以借助 lint 工具。不值得介绍可能产生的那种意想不到的后果。毕竟,python 的重点是易于读写。

于 2013-09-24T15:20:56.730 回答
0

TL;DR:这是一个功能。

我认为默认情况下应该进行这种类型的优化,因为它等同于:Python 有设计的副作用。y=g(f(x))a=f(x) ; y=g(a)

本地命名空间旨在在 Python 本身内访问:它们具有明确定义的 API。该eval函数的文档和exec语句 (Python >= 2.4) 声明“如果提供,本地变量可以是任何映射对象”。

一种可能的应用是用 Python 编写 Python 调试器。我可以子类化dict,以便本地命名空间中的每次读/写都会触发一些 GUI 事件;我现在能够观察 和 之间的中间a结果。如果没有这种可能性,我将不得不检查 CPython 虚拟堆栈,或者它们在任何其他 Python 实现中使用的任何东西。a=f(x)y=g(a)

除了调试之外,我还看到了此功能的其他可能用途。我可以想象将 Python 嵌入到视频游戏引擎中。负责故事、任务、角色、事件等所有内容的设计师在这里将他们的想象力转化为游戏内容,而不是编写代码。为了让他们的生活更轻松,我可以使用带有一些预加载和/或实时值的特殊本地命名空间来运行他们的脚本。名称my_hptheir_hp将始终返回/设置触发脚本的“攻击”事件中涉及的两个生物的当前生命值数。我的设计师不需要一直打字self.(他们甚至不知道类和对象)。在某种方式,my_hp将充当全局或描述符,除了它对生物来说是本地的并且不需要显式的类/实例取消引用。这比尝试解析他们的脚本并猜测我们何时必须self在前面添加内容要容易得多。

简而言之:你永远不知道虚拟机会对你的代码做什么,所以看起来相同的事情并不总是如此。

于 2015-08-18T14:31:51.987 回答