Python是否在运行时自动优化(在某种程度上)?

时间:2014-01-23 22:02:04

标签: python

我很想知道。例如,如果我想检查一个数字是否是偶数,则其中任何一个都可以工作:

# values are True if even, False if odd
even_masked = not (number & 0x1)
even_modulo = (number%2 == 0)

它们都做同样的事情,但第一种方法在时钟周期方面要快得多。在C中你可以设置编译器为你做这样的优化,但Python解释器是否做了类似的事情?

2 个答案:

答案 0 :(得分:0)

由于dis模块:

,这两个函数的字节码不同
>>> def test(number):
...     even_masked = not (number & 0x1)
...
>>> def test2(number):
...     even_modulo = (number%2 == 0)
...
>>> dis.dis(test)
  2           0 LOAD_FAST                0 (number)
              3 LOAD_CONST               1 (1)
              6 BINARY_AND
              7 UNARY_NOT
              8 STORE_FAST               1 (even_masked)
             11 LOAD_CONST               0 (None)
             14 RETURN_VALUE
>>> dis.dis(test2)
  2           0 LOAD_FAST                0 (number)
              3 LOAD_CONST               1 (2)
              6 BINARY_MODULO
              7 LOAD_CONST               2 (0)
             10 COMPARE_OP               2 (==)
             13 STORE_FAST               1 (even_modulo)
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

但是......我们可以看到两种方法之间的区别很小:

>>> timeit.timeit("even_modulo = (number%2 == 0)", setup="number=1", number=100000000)
11.886679887771606
>>> timeit.timeit("even_masked = not (number & 0x1)", setup="number=1", number=100000000)
11.225641965866089

因此,请保持脚本可读,而不是进行此类优化。理解第一行的时间将比执行中节省的时间更重要,即使您的脚本被使用了数百万次: - )

答案 1 :(得分:0)

dis模块显示了Python所做的说明

not (number & 0x1)

          0 LOAD_GLOBAL              0 (number)
          3 LOAD_CONST               1 (1)
          6 BINARY_AND
          7 UNARY_NOT
          8 POP_TOP

(number%2 == 0)

          0 LOAD_GLOBAL              0 (number)
          3 LOAD_CONST               1 (2)
          6 BINARY_MODULO
          7 LOAD_CONST               2 (0)
         10 COMPARE_OP               2 (==)
         13 POP_TOP

你给它的表达看起来很文字。