2011-03-30 55 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表現得應該如此。