❶ 為什麼大多數編程語言沒有針對尾遞歸做優化
python本身是不支持尾遞歸的(via),並且對遞歸次數有限制的,當遞歸次數超過1000次的時候,就會拋出「RuntimeError: maximum recursion depth exceeded」異常。
❷ 如何看待以及理解Python的這種尾遞歸優化
TCO,tail-call optimization,其實有多種解讀方式。
最常見的解讀方式是:對於尾調用的函數調用,不要浪費棧空間,而要復用調用者的棧空間。這樣的結果就是一長串尾調用不會爆棧,而沒有TCO的話同樣的調用就會爆棧。
從這個意義上說,題主貼的那個recipe確實達到了TCO的部分目的:
通過stack introspection查看調用鏈上的調用者之中有沒有自己
有的話,通過拋異常來迫使棧回退(stack unwind)到之前的一個自己的frame
在回退到的frame接住異常,拿出後來調用的參數,用新參數再次調用自己
這樣就可以讓尾遞歸不爆棧。但這樣做性能是沒保證的…而且對於完全沒遞歸過的一般尾調用也不起作用。
一種對TCO的常見誤解是:由編譯器或運行時系統把尾調用/尾遞歸實現得很快。這不是TCO真正要強調的事情——不爆棧才是最重要的。也就是說其實重點不在「優化」,而在於「尾調用不爆棧」這個語義保證。
「proper tail-call」的叫法遠比「tail-call optimization」來得合適。
因而像題主說的那種做法,可以算部分TCO,但算不上「性能優化」意義上的優化。
❸ 在Python 中,yield 對遞歸函數的性能提高表現在哪裡,程度如何
遞歸式方法可以被用於解決很多的計算機科學問題,因此它是計算機科學中十分重要的一個概念。
絕大多數編程語言支持函數的自調用,在這些語言中函數可以通過調用自身來進行遞歸。計算理論可以證明遞歸的作用可以完全取代循環,因此在很多函數編程語言(如Scheme)中習慣用遞歸來實現循環。
計算機科學家尼克勞斯·維爾特如此描述遞歸:
遞歸的強大之處在於它允許用戶用有限的語句描述無限的對象。因此,在計算機科學中,遞歸可以被用來描述無限步的運算,盡管描述運算的程序是有限的。
python 2 遞歸函數和其它語言,基本沒有差別,只是不支持尾遞歸。無限遞歸最大值為固定的,但可以修改。
❹ 如何在Python中實現尾遞歸優化
將尾遞歸優化改為循環
❺ 關於python遞歸函數怎樣理解
遞歸的思想主要是能夠重復某些動作,比如簡單的階乘,次方,回溯中的八皇後,數獨,還有漢諾塔,分形。
由於堆棧的機制,一般的遞歸可以保留某些變數在歷史狀態中,比如你提到的return
x
*
power...,
但是某些或許龐大的問題或者是深度過大的問題就需要盡量避免遞歸,因為可能會棧溢出。還有一個問題是~python不支持尾遞歸優化!!!!所以~還是盡量避免遞歸的出現。
def
power(x,
n)
if
n
<
0:
return
1
return
x
*
power(x,
n
-
1)
power(3,
3)
3
*
power(3,
2)
3
*
(3
*
power(3,
1))
3
*
(3
*
(3
*
power(3,
0)))
3
*
(3
*
(3
*
1))
這里n
=
0,
return
1
3
*
(3
*
3)
3
*
9
27
當函數形參n=0的時候,開始回退~直到第一次調用power結束。
❻ 遞歸與偽遞歸區別,Python 實現遞歸與尾遞歸
(1)數據的定義是按遞歸定義的。(n的階乘)
(2)問題解法按遞歸實現。(回溯)
(3)數據的結構形式是按遞歸定義的。(二叉樹的遍歷,圖的搜索)
❼ python 循環內要處理大量數據時怎麼優化
先嘗試優化程序的時間復雜度,尋找更有效的演算法
確保了演算法復雜度在可接受范圍之內後,開始進行常數優化,以下是Python優化的幾個小技巧:
實測表明,for語句一般比while語句效率更高
同樣實測表明,xrange一般比range要高效
如果要存儲動態數據(即有可能頻繁變動的數據)少用list和str,多用dict
實測表明,
兩個str的連接效率從高到低+=,join,+
多個str的連接效率從高到低join,+=,+
盡可能使用列表解析表達式和生成器表達式代替循環一遍來構建list
避免使用global關鍵字,無論是從代碼效率還是可移植性的方面考慮
❽ Python嵌套循環優化問題
循環次數一樣的,如果對於循環的性能有要求,建議使用列表生成,它使用c實現,比自帶的for性能高。
❾ python 尾遞歸不會 棧溢出嗎
一樣會溢出,python沒有對尾遞歸做優化