2011-03-30 128 views
3

有人可以解释为什么会发生这种情况吗?Python时间不工作?

[email protected] ~ $ time python /usr/lib64/python2.7/timeit.py -n 1 \ 
    -- 'x = 10**1000' 
1 loops, best of 3: 0.954 usec per loop 

real 0m0.055s 
user 0m0.050s 
sys  0m0.000s 

[email protected] ~ $ time python /usr/lib64/python2.7/timeit.py -n 1 \ 
    -- 'x = 10**100000' 
1 loops, best of 3: 0.954 usec per loop 

real 0m0.067s 
user 0m0.040s 
sys  0m0.020s 

[email protected] ~ $ time python /usr/lib64/python2.7/timeit.py -n 1 \ 
    -- 'x = 10**10000000' 
1 loops, best of 3: 0.954 usec per loop 

real 0m20.802s 
user 0m20.540s 
sys  0m0.170s 

我得到完全相同的结果从timeit,但time告诉我,评估10**10000000时间超过20秒。如果我叫timeit从解释同样的情况:

>>> t = time.time() 
>>> print timeit.timeit('x = 10**10000000;', number=1) 
5.00679016113e-06 
>>> print time.time() - t 
20.6168580055 

为什么我timeit不工作,或者我究竟做错了什么?

附加信息:

>>> print sys.version 
2.7.1+ (2.7:4f07cacb2c3b+, Mar 28 2011, 23:11:59) 
[GCC 4.4.5] 

>>> print sys.version_info 
>>> sys.version_info(major=2, minor=7, micro=2, releaselevel='alpha', serial=0) 

UPDATE:

这里还有一个非常有趣的现象:

>>> def run(): 
...  t = time.time() 
...  x = 10**10000000 
...  print time.time() - t 

当我按下定义这个功能之后进入,它需要大约半分钟直到我回到提示。然后:

>>> run() 
2.14576721191e-06 

为什么会发生这种情况?函数体是否被预编译或优化?

回答

5

我的猜测是问题在于你如何陈述问题到timeit。我认为发生的事情是表达式在编译测试表达式时被评估一次,然后只用每个timeit循环来看(而不是重新评估)。所以你现在所测量的是完成分配而不是计算所需的时间。

你需要强制计算每次发生:

timeit.timeit('x = 10; y = 100; z = x ** y') 

编辑:在回答你的问题,后来在函数体被优化。编译器看到10*100000并意识到它不会改变,所以在编译时计算它而不是运行时。

+0

你是对的,强迫计算发生每次都会延长时间。我不知道Python会为我预先计算表达式。 – 2011-03-30 13:02:28

+0

@Attila - 我到现在都没有。 – 2011-03-30 13:06:57

4

比较:

>>> import dis 
>>> def run(): 
...  return 10**100 
... 
>>> dis.dis(run) 
    3   0 LOAD_CONST    3 (100000000000000000000000000000000000 
00000000000000000000000000000000000000000000000000000000000000000L) 
       3 RETURN_VALUE   

而且

>>> def runvar(): 
...  x = 10 
...  return x**100 
... 
>>> dis.dis(runvar) 
    3   0 LOAD_CONST    1 (10) 
       3 STORE_FAST    0 (x) 

    4   6 LOAD_FAST    0 (x) 
       9 LOAD_CONST    2 (100) 
      12 BINARY_POWER   
      13 RETURN_VALUE   

注意BINARY_POWER在运行时只在第二种情况下执行。因此timeit表现得应该如此。