似乎python(2.6)无法优化这个简单的临时变量'a'?
我用来为某些代码分配一个局部变量,以减少行长度。
对我来说,这是一个简单的优化,任何正确的编译器都可以自动完成。
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)
输出:
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
为什么它无法自动删除?
11 5 LOAD_GLOBAL 0 (functioncall)
8 STORE_FAST 0 (a)
答案 0 :(得分:5)
if __debug__
下的代码之一)并且我确实认为有某种窥视孔优化器,但我认为编译阶段的速度相当快,排除了进行大量分析。
可维护性似乎也是核心Python开发人员的关键。这里是a thread from 2009,其中考虑了删除死代码的补丁,然后被拒绝,因为它会使编译器的可维护性降低。
如果你想要高性能,你需要的不是CPython;也许PyPy会有所帮助。 Python通常经过优化以节省程序员时间,而不是运行时。如果您不想在字节码中使用死代码,请不要将其放在源代码中。 : - )
答案 1 :(得分:1)
原则上,Python解释器可以对此进行优化。
在实践中,人们使用Python编程,因为在其中编写代码的速度很快,而不是因为使用它编写的代码很快。所以在这种特殊情况下,程序员应该进行优化。
答案 2 :(得分:0)
在python中,你的源代码并没有完全消失 - def
语句是一个可执行语句,用于创建一个函数对象。你在问为什么python不会巧妙地做一些事情,而不是优化名称中的问题。
如果需要,借助于棉绒工具,这种优化很容易手工完成。引入可能产生的意外后果并不值得。毕竟,python的重点是易于阅读和编写。
答案 3 :(得分:0)
TL; DR:这是一个功能。
我认为这种类型的优化不默认情况下 ,因为y=g(f(x))
不等同于{{1这里有Python的副作用。
本地命名空间旨在在Python本身中访问:它们具有明确定义的API。 a=f(x) ; y=g(a)
函数和eval
语句(Python> = 2.4)的文档声明“如果提供,则locals可以是任何映射对象”。
一个可能的应用是在Python中编写Python调试器。我可以继承exec
,以便本地命名空间中的每个读/写触发一些GUI事件;我现在能够在dict
和a
之间观察到中间结果a=f(x)
。没有这种可能性,我将不得不检查CPython虚拟堆栈,或者在任何其他Python实现中使用它们。
除了调试之外,我还看到了此功能的其他可能用途。我可以想象在视频游戏引擎中嵌入Python。负责故事,任务,角色,事件以及所有这些事情的设计师将他们的想象力转化为游戏内容,而不是编写代码。为了让他们的生活更轻松,我可以使用特殊的本地命名空间运行他们的脚本,该命名空间带有一些预加载和/或实时值。
名称y=g(a)
和my_hp
将始终返回/设置触发脚本的“攻击”事件中涉及的两个生物的当前生命点数。我的设计师不需要一直输入their_hp
(他们甚至不知道类和对象)。在某种程度上,self.
将表现为全局或描述符,除了它对于生物来说是本地的,并且不需要显式的类/实例去引用。实现这种方式比尝试解析脚本更容易,并猜测我们何时必须在内容之前添加my_hp
。
简而言之:您永远不知道虚拟机将对您的代码执行什么操作,因此可能看起来相同的内容并非总是如此。