2013-02-14 17 views
1

如果我像這樣定義一個函數:是否允許Python優化函數定義以消除未使用的代碼?

def ccid_year(seq): 
    year, prefix, index, suffix = seq 
    return year 

是Python的允許來優化它是有效的:因爲它的文件的格式

def ccid_year(seq): 
    return seq[0] 

我寧願寫的第一功能數據被傳入,但希望Python能夠生成與第二個定義一樣有效的代碼。

+0

不要命名你的變量'元組'。 – 2013-02-14 18:23:16

+2

不太可能;如果您打開包裝時傳入的'seq'有副作用?一般情況下,python的動態類型在編譯時不可能通過做出你需要做的假設來進行優化。 – geoffspear 2013-02-14 18:29:01

+0

此外,請參閱Pypy項目@ http://speed.pypy.org/(比現在的cPython快大約5倍以上) - 關於上面的樣式,我建議不要使用這樣的變量 - 只是發表評論 – orokusaki 2013-02-14 18:32:09

回答

2

的兩個功能是不等效的:

def ccid_year_1(seq): 
    year, prefix, index, suffix = seq 
    return year 

def ccid_year_2(seq): 
    return seq[0] 

arg = {1:'a', 2:'b', 0:'c', 3:'d'} 
print ccid_year_1(arg) 
print ccid_year_2(arg) 

第一呼叫打印0和第二打印c

+0

我不要認爲拆開字典是一個好主意。特別是因爲'.keys()'的順序是依賴於實現的。 – C2H5OH 2013-07-29 10:16:24

2

我會稍後回答面值的問題,但首先:如有疑問,請以此爲基準!但首先回想一下,大部分時間都花費在一小部分代碼中(即大多數代碼與性能無關!),而在CPython中,函數調用開銷通常主宰小的低效率。更不用說大規模算法的低效率(也就是嚇唬愚蠢的代碼)使微觀優化問題變得相形見絀。

所以要麼根本不用擔心,要麼如果你有理由擔心它,首先是基準的替代方案,其次是不把它放在函數中。請注意,「擔心它的原因」必須根據所花費的時間和手動優化的維護負擔(如果有的話)加權。

CPython是您最喜歡使用的參考實現,它是保守的關於這個級別的優化。雖然有一個窺視優化器在字節碼上運行,但它的規模有限。更一般地說,你不能期望通過單個語句進行很多優化。靜態優化Python代碼的問題在於,即使最無辜的程序分區可以調用任意代碼,這可能會做任何事情,所以你不能忽略這些調用。 雖然我們在此,但如果seq的類型錯誤(不是序列或非常奇怪的序列)或長度(不是非常奇怪的序列),而是您提出的優化是無效的(從程序的意義上說,它沒有相同的行爲)正好三個項目長)!任何聲稱實現Python的程序都必須保持這種差異,所以它不會從字面上進行你所建議的轉換。我認爲這只是一個副手的例子,但它確實表明你嚴重低估了Python的複雜程度(要實現,而且要加倍地優化)。之前我和其他人已經詳細寫過這篇文章,所以我會在這篇文章變得更大之前停下來。如果這個函數確實是從一個熱循環中調用的話,PyPy可能會優化這個以及其他一些你甚至沒有想到的,而將它編譯成一個機器代碼循環,迭代速度比任何Python循環都能在CPython上迭代得快。它仍然會包含一些檢查來突破循環,並在必要時採取適當的行動(例如引發異常),但如果沒有觸發,它們也會非常高效。

我對IronPython和Jython以及其他實現知之甚少,但如果它們缺少一致性比CPython基準測試結果快一倍的指標,那麼它們不會執行顯着的優化。雖然虛擬機IronPython和Jython包含了JIT編譯器(但並不完全不像PyPy),這些JIT編譯器是爲非常不同的語言而構建的,我會很驚訝的,如果他們可以查看代碼IronPython/Jython必須執行以實現Python語義並對其進行優化。