Python中函数定义耗时太长
为什么在定义的时候,Python要计算p
的值?这让这个函数的定义变得特别慢。
def f():
raise Exception('Some error')
p = 2322111239**42322222334923492304923
print 'Defined!'
另外,如果p
的值是在定义时计算的,那为什么定义这个函数的时候没有出错呢?
def f():
return 4
p = 11/0
这个例子显然没问题,因为没有涉及常量:
def f():
raise Exception('Some error')
x=42322222334923492304923
p = 2322111239**x
print 'Defined!'
3 个回答
3
我们来试试一个更合理的数字:
>>> def f():
... p=123**45
...
如果你使用 dis 来查看字节码,你会发现 p 的值是在函数被调用之前就已经定义好了:
>>> import dis
>>> dis.dis(f)
2 0 LOAD_CONST 3 (11110408185131956285910790587176451918559153212268021823629073199866111001242743283966127048043)
3 STORE_FAST 0 (p)
6 LOAD_CONST 0 (None)
9 RETURN_VALUE
8
这是一个叫做“窥视优化器”的东西:
特别要注意第104-106行:
case BINARY_POWER:
newconst = PyNumber_Power(v, w, Py_None);
break;
它的目的是加快函数的运行速度,虽然在导入模块时定义的速度会慢一些。这个想法是,你只需要编译一次函数的代码,但可能会调用很多次。而且,对于两个常量的指数运算结果是不会改变的,所以每次都重新计算就没必要了。
注意:在Python 3中,常量折叠已经转移到了新的AST优化器中,具体在ast_opt.c
里,peephole.c
已经不再使用。现在的代码有保护措施,以防止过于激进的优化,这种优化可能会导致解析/编译步骤变得缓慢或占用过多内存,就像这个问题中所展示的那样。