2014-01-13 55 views
0

我是一名python初學者。我想知道...這兩個(Python)代碼示例有什麼區別?

問題1:sample2比bit1快一點,內存使用少一點?(因爲它沒有聲明和分配變量)

Q2:哪個樣本更適合'大'程序?(是什麼關係,即使是大項目的區別?)

樣本1:

session = request.session 
session['v1'] = 1 
session['v2'] = 2 
session['v2'] = 3 
if session['v1'] == 1: 
    session['v4'] = 4 

樣品2:

request.session['v1'] = 1 
request.session['v2'] = 2 
request.session['v2'] = 3 
if request.session['v1'] == 1: 
    request.session['v4'] = 4 

不是一個過早的優化。只是爲了解...

+2

在您的計算機上運行一些測試,timeit!如果這些不是在大循環中運行,我懷疑你會看到任何性能差異。屬性查找在python中有多昂貴? – dm03514

回答

5

第一個代碼是更快,因爲它避免了所有查​​找request及其屬性。見字節碼的區別:

In [6]: dis.dis(test_first) 
    2   0 LOAD_GLOBAL    0 (request) 
       3 LOAD_ATTR    1 (session) 
       6 STORE_FAST    0 (session) 

    3   9 LOAD_CONST    1 (1) 
      12 LOAD_FAST    0 (session) 
      15 LOAD_CONST    2 ('v1') 
      18 STORE_SUBSCR   

    4   19 LOAD_CONST    3 (2) 
      22 LOAD_FAST    0 (session) 
      25 LOAD_CONST    4 ('v2') 
      28 STORE_SUBSCR   

    5   29 LOAD_CONST    5 (3) 
      32 LOAD_FAST    0 (session) 
      35 LOAD_CONST    4 ('v2') 
      38 STORE_SUBSCR   

    6   39 LOAD_FAST    0 (session) 
      42 LOAD_CONST    2 ('v1') 
      45 BINARY_SUBSCR   
      46 LOAD_CONST    1 (1) 
      49 COMPARE_OP    2 (==) 
      52 POP_JUMP_IF_FALSE  68 

    7   55 LOAD_CONST    6 (4) 
      58 LOAD_FAST    0 (session) 
      61 LOAD_CONST    7 ('v4') 
      64 STORE_SUBSCR   
      65 JUMP_FORWARD    0 (to 68) 
     >> 68 LOAD_CONST    0 (None) 
      71 RETURN_VALUE 

對戰:

In [7]: dis.dis(test_second) 
    2   0 LOAD_CONST    1 (1) 
       3 LOAD_GLOBAL    0 (request) 
       6 LOAD_ATTR    1 (session) 
       9 LOAD_CONST    2 ('v1') 
      12 STORE_SUBSCR   

    3   13 LOAD_CONST    3 (2) 
      16 LOAD_GLOBAL    0 (request) 
      19 LOAD_ATTR    1 (session) 
      22 LOAD_CONST    4 ('v2') 
      25 STORE_SUBSCR   

    4   26 LOAD_CONST    5 (3) 
      29 LOAD_GLOBAL    0 (request) 
      32 LOAD_ATTR    1 (session) 
      35 LOAD_CONST    4 ('v2') 
      38 STORE_SUBSCR   

    5   39 LOAD_GLOBAL    0 (request) 
      42 LOAD_ATTR    1 (session) 
      45 LOAD_CONST    2 ('v1') 
      48 BINARY_SUBSCR   
      49 LOAD_CONST    1 (1) 
      52 COMPARE_OP    2 (==) 
      55 POP_JUMP_IF_FALSE  74 

    6   58 LOAD_CONST    6 (4) 
      61 LOAD_GLOBAL    0 (request) 
      64 LOAD_ATTR    1 (session) 
      67 LOAD_CONST    7 ('v4') 
      70 STORE_SUBSCR   
      71 JUMP_FORWARD    0 (to 74) 
     >> 74 LOAD_CONST    0 (None) 
      77 RETURN_VALUE 

通知所有額外LOAD_GLOBAL和第二字節碼LOAD_ATTR和記住,LOAD_FASTLOAD_GLOBAL,因爲LOAD_FAST做一個簡單的數組查找,而LOAD_GLOBAL必須查找全局字典(它需要計算變量的哈希等)。

第一個版本有一個LOAD_GLOBAL和一個LOAD_ATTR

事實上,如果我們測試其速度:

In [8]: %timeit test_first() 
1000000 loops, best of 3: 343 ns per loop 

In [9]: %timeit test_second() 
1000000 loops, best of 3: 542 ns per loop 

第一個是幾乎快一倍。 但是請注意,它們都很快,而且速度可能並不重要。 如果request是局部變量,速度差異會減少一點。

第二個還有一個缺點:它重複了很多次相同的事情。使代碼變得更大,可讀性更差並且引入錯別字的機會更大。 這是,我相信,只有事情的重要這些片段。 如果您是出於性能原因選擇它們,那絕對是不成熟的優化。

+0

請注意,如果request是本地的,則時間差縮小一點。本地查找按索引排列在數組中,而全局查找則使用字典中的鍵(需要散列計算)。 –

+0

@MartijnPieters是的,我現在要指出。 – Bakuriu

+1

而且由於本地名稱只是表中的一個條目和對已經存在的變量的引用,因此內存使用情況不會受到影響。 –

2

它可能沒有太大的區別。第一種解決方案可能無限快地加快。

除了您的解決方案(包括罰款),並假設的request.session是類似字典的,你可能會考慮:根據變化的數量

request.session.update({ 
    'v1': 1, 
    'v2': 2, 
    … 
}) 

,以及是否新的信息已經在一個字典。

+0

感謝@kojiro。 – St123