use*_*234 18 python floating-point integer casting
将整数转换为float的原因是什么比在Python中向该int添加0.0要慢?
import timeit
def add_simple():
for i in range(1000):
a = 1 + 0.0
def cast_simple():
for i in range(1000):
a = float(1)
def add_total():
total = 0
for i in range(1000):
total += 1 + 0.0
def cast_total():
total = 0
for i in range(1000):
total += float(1)
print "Add simple timing: %s" % timeit.timeit(add_simple, number=1)
print "Cast simple timing: %s" % timeit.timeit(cast_simple, number=1)
print "Add total timing: %s" % timeit.timeit(add_total, number=1)
print "Cast total timing: %s" % timeit.timeit(cast_total, number=1)
Run Code Online (Sandbox Code Playgroud)
其输出是:
添加简单的时间:0.0001220703125
投简单时间:0.000469923019409
添加总计时:0.000164985656738
总计时间:0.00040078163147
Way*_*ner 16
如果您使用该dis模块,您可以开始了解原因:
In [11]: dis.dis(add_simple)
2 0 SETUP_LOOP 26 (to 29)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1000)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (i)
3 19 LOAD_CONST 4 (1.0)
22 STORE_FAST 1 (a)
25 JUMP_ABSOLUTE 13
>> 28 POP_BLOCK
>> 29 LOAD_CONST 0 (None)
32 RETURN_VALUE
In [12]: dis.dis(cast_simple)
2 0 SETUP_LOOP 32 (to 35)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1000)
9 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
12 GET_ITER
>> 13 FOR_ITER 18 (to 34)
16 STORE_FAST 0 (i)
3 19 LOAD_GLOBAL 1 (float)
22 LOAD_CONST 2 (1)
25 CALL_FUNCTION 1 (1 positional, 0 keyword pair)
28 STORE_FAST 1 (a)
31 JUMP_ABSOLUTE 13
>> 34 POP_BLOCK
>> 35 LOAD_CONST 0 (None)
38 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
请注意 CALL_FUNCTION
Python中的函数调用(相对)很慢.和.查找一样.因为强制转换float需要函数调用 - 这就是它变慢的原因.
use*_*ica 11
如果你看一下字节码add_simple:
>>> dis.dis(add_simple)
2 0 SETUP_LOOP 26 (to 29)
3 LOAD_GLOBAL 0 (range)
6 LOAD_CONST 1 (1000)
9 CALL_FUNCTION 1
12 GET_ITER
>> 13 FOR_ITER 12 (to 28)
16 STORE_FAST 0 (i)
3 19 LOAD_CONST 4 (1.0)
22 STORE_FAST 1 (a)
25 JUMP_ABSOLUTE 13
>> 28 POP_BLOCK
>> 29 LOAD_CONST 0 (None)
32 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
你会发现0.0那里实际上并不存在.它只是加载常量1.0并将其存储到a.Python在编译时计算了结果,所以你实际上并没有对添加进行计时.
如果你使用一个变量1,那么Python的原始窥孔优化器不能在编译时添加,添加0.0仍然有一个导致:
>>> timeit.timeit('float(a)', 'a=1')
0.22538208961486816
>>> timeit.timeit('a+0.0', 'a=1')
0.13347005844116211
Run Code Online (Sandbox Code Playgroud)
调用float需要两个dict查找来确定是什么float,一个在模块的全局命名空间中,另一个在内置命令中.它还具有Python函数调用开销,这比C函数调用更昂贵.
添加0.0只需要索引到函数的代码对象中co_consts以加载常量0.0,然后调用和类型的C级nb_add函数来执行添加.总体而言,这是一个较低的开销量.intfloat