2015-10-17 22 views
1

所以將這個parpython的部分內聯調用?

path = u'/a/b/c' 
lam = lambda f: f.lower().startswith(u'distantlod') 
par = functools.partial(lam, path) 

par

path = u'/a/b/c' 
startsWith = path.lower().startswith 
par = lambda: startsWith(u'distantlod') 

等同?如果不是爲什麼?

+1

也許相關:[functools.partial提供什麼功能,您無法通過lambdas?](http://stackoverflow.com/questions/3252228/python-why-is-functools-partial-necessary) – yuvi

+0

@yuvi:這是相關的,但不回答這個特定的問題 - 也是相關的是:http://stackoverflow.com/q/17388438/281545 –

+2

你能澄清你如何定義「等效」? – jamesc

回答

0

這裏是我的cProfile實驗,看看我能否確認@ yuvi的測量結果。

CODEpar_profile.py

import cProfile as profile 
import functools 


path = u'/a/b/c' 

lam = lambda f: f.lower().startswith(u'distantlod') 
par = functools.partial(lam, path) 

startsWith = path.lower().startswith 
par2 = lambda: startsWith(u'distantlod') 


if __name__ == '__main__': 
    profile.run("for _ in range(1000000): par()") 
    profile.run("for _ in range(1000000): par2()") 

OUT

$ python par_profile.py 
     3000003 function calls in 0.536 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.148 0.148 0.536 0.536 <string>:1(<module>) 
    1000000 0.242 0.000 0.388 0.000 par_profile.py:7(<lambda>) 
     1 0.000 0.000 0.536 0.536 {built-in method exec} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
    1000000 0.054 0.000 0.054 0.000 {method 'lower' of 'str' objects} 
    1000000 0.092 0.000 0.092 0.000 {method 'startswith' of 'str' objects} 


     2000003 function calls in 0.347 seconds 

    Ordered by: standard name 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.130 0.130 0.347 0.347 <string>:1(<module>) 
    1000000 0.126 0.000 0.218 0.000 par_profile.py:11(<lambda>) 
     1 0.000 0.000 0.347 0.347 {built-in method exec} 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
    1000000 0.092 0.000 0.092 0.000 {method 'startswith' of 'str' objects} 

首先,它看起來像我的機器理貨與@ yuvi的數字這些測量:

  • par是約540納秒
  • par2大約是350納秒

所以我同意par2看起來大約200 ns的更快。

看起來,如果你想比較lambdapartial這不是一個公平的測試 - par2少了一個電話,因爲它不叫lower,而par一樣。

爲了說明爲什麼,startsWith可以改寫爲:

lower_path = path.lower() 
startsWith = lower_path.startswith 

...所以par2只是一個lambda包含單個startswithpar是部分同時包含lowerstartswith電話。

因此它們不是等效的,因此par比較慢。

爲什麼?

問題是「爲什麼f.lower().startswith未內聯 - 禁止語言內聯?」

首先,這條巨蟒本身並不禁止這種內聯的 - 這是不同的Python實現,使決策,在我的測試中,它上面的情況是CPython的3

其次,partial的工作是不是內聯函數,它只是...

「凍結」的函數的參數和/或產生新的對象,具有簡化的簽名(doc

不是關鍵字某些部分如果你正在尋找的東西,會做內聯在Python,那麼我會看看Numba's jit之類的東西,或者用PyPy運行一些實驗(如果你發現一些有趣的改進,請回到這裏)。

如果您無法找到任何可以執行內聯操作的任何內容,那麼對於新的Python模塊來說,這可能是一個很好的例子!

+0

謝謝 - 但是我問的是_why_'f.lower()。startswith'沒有內聯 - 什麼禁止語言內聯? –

+0

已更新,以包含我爲什麼回答。希望你覺得它有幫助。 – jamesc