2012-08-12 250 views

回答

12

有幾乎是在工作蟒蛇執行的任何陳述有所不同:

>>> import dis 
>>> def inplace_add(): 
...  a = 0 
...  a += 1 
... 
>>> def add_and_assign(): 
...  a = 0 
...  a = a + 1 
... 
>>> dis.dis(inplace_add) 
    2   0 LOAD_CONST    1 (0) 
       3 STORE_FAST    0 (a) 

    3   6 LOAD_FAST    0 (a) 
       9 LOAD_CONST    2 (1) 
      12 INPLACE_ADD   
      13 STORE_FAST    0 (a) 
      16 LOAD_CONST    0 (None) 
      19 RETURN_VALUE   
>>> dis.dis(add_and_assign) 
    2   0 LOAD_CONST    1 (0) 
       3 STORE_FAST    0 (a) 

    3   6 LOAD_FAST    0 (a) 
       9 LOAD_CONST    2 (1) 
      12 BINARY_ADD   
      13 STORE_FAST    0 (a) 
      16 LOAD_CONST    0 (None) 
      19 RETURN_VALUE   

的區別是一個INPLACE_ADD與一個BINARY_ADD

產生的時序是分不出哪一個會更快:

>>> import timeit 
>>> timeit.timeit('inplace_add', 'from __main__ import inplace_add', number=10000000) 
0.32667088508605957 
>>> timeit.timeit('add_and_assign', 'from __main__ import add_and_assign', number=10000000) 
0.34172606468200684 

因此,在蟒蛇,不同的是可以忽略不計。不要擔心。

+0

很好的回答(我不知道'dis'模塊,所以謝謝你)。一個考慮因素是執行速度可能會受到給定時間運行的其他進程的影響。因此,我的方法是在一個函數中運行100萬次,並在'cProfile'中多次比較執行速度(見下文)。我同意這種差異是微不足道的。 – 2012-08-13 06:22:48

4

都能跟得上

>>> bar = timeit.Timer("a += 1", "a = 0") 
>>> bar.timeit(number=1000000) 
0.064391136169433594 
>>> bar = timeit.Timer("a = a + 1", "a = 0") 
>>> bar.timeit(number=1000000) 
0.064393997192382812 
>>> 
2

是的,但差別很小。

>>> timeit.Timer('x += 1', 'x = 0').timeit(10**8) 
5.7387330532073975 
>>> timeit.Timer('x = x + 1', 'x = 0').timeit(10**8) 
6.04801607131958 
>>> timeit.Timer('x += 1', 'x = 0').timeit(10**8) 
5.790481090545654 
>>> timeit.Timer('x = x + 1', 'x = 0').timeit(10**8) 
6.083467960357666 
1

我把使用cProfile模塊稍微不同的方法:

$ python -m cProfile test.py 
    4 function calls in 0.397 seconds 

Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.397 0.397 test.py:2(<module>) 
     1 0.205 0.205 0.205 0.205 test.py:2(add1) 
     1 0.192 0.192 0.192 0.192 test.py:6(add2) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 




[email protected]:~/pyad$ cat test.py 
def add1(a): 
    for x in xrange(10 ** 6): 
     a += 1 

def add2(a): 
    for x in xrange(10 ** 6): 
     a = a + 1 

add1(0) 
add2(0) 

後約20運行我會總結(使用a = a + 1),其ADD2非常稍快,但不是在所有情況下(也許嘗試更多的循環)。這可能不是最好的啓發式算法,但我認爲更大數量的重複次數應該表示性能差異。

編輯 - 結果10個** 9來電:

1 216.119 216.119 216.119 216.119 test.py:2(add1) 
    1 195.364 195.364 195.364 195.364 test.py:6(add2)