日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

知识点讲解八:Python中的尾递归

發布時間:2025/4/5 python 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 知识点讲解八:Python中的尾递归 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

尾遞歸

**尾遞歸的原理:**當編譯器檢測到一個函數調用是尾遞歸的時候,它就覆蓋當前的活動記錄而不是在棧中去創建一個新的。編譯器可以做到這點,因為遞歸調用是當前活躍期內最后一條待執行的語句,于是當這個調用返回時棧幀中并沒有其他事情可做,因此也就沒有保存棧幀的必要了。通過覆蓋當前的棧幀而不是在其之上重新添加一個,這樣所使用的棧空間就大大縮減了,這使得實際的運行效率會變得更高。


換一種說法,尾遞歸是指,在函數返回的時候,調用自身本身,并且,return語句不能包含表達式。這樣,編譯器或者解釋器就可以把尾遞歸做優化,使遞歸本身無論調用多少次,都只占用一個棧幀,不會出現棧溢出的情況。

def facttail(int n, int res) {if (n < 0)return 0;else if(n == 0)return 1;else if(n == 1)return res;elsereturn facttail(n - 1, n *res); }

需要注意的是python 不支持尾遞歸,遞歸深度超過1000時會報錯,故此需要我們做一些處理來解決這個問題。

尾遞歸優化

通過實現一個 tail_call_optimized 裝飾器,來優化尾遞歸。

#!/usr/bin/env python2.4 # This program shows off a python decorator( # which implements tail call optimization. It # does this by throwing an exception if it is # it's own grandparent, and catching such # exceptions to recall the stack.import sysclass TailRecurseException:def __init__(self, args, kwargs):self.args = argsself.kwargs = kwargsdef tail_call_optimized(g):"""This function decorates a function with tail calloptimization. It does this by throwing an exceptionif it is it's own grandparent, and catching suchexceptions to fake the tail call optimization.This function fails if the decoratedfunction recurses in a non-tail context."""def func(*args, **kwargs):f = sys._getframe()if f.f_back and f.f_back.f_back \and f.f_back.f_back.f_code == f.f_code:# 拋出異常raise TailRecurseException(args, kwargs)else:while 1:try:return g(*args, **kwargs)except TailRecurseException, e:args = e.argskwargs = e.kwargsfunc.__doc__ = g.__doc__return func@tail_call_optimized def factorial(n, acc=1):"calculate a factorial"if n == 0:return accreturn factorial(n-1, n*acc)print factorial(10000)

這里解釋一下sys._getframe()函數:

sys._getframe([depth]):
Return a frame object from the call stack.
If optional integer depth is given, return the frame object that many calls below the top of the stack.
If that is deeper than the call stack, ValueEfror is raised. The default for depth is zero,
returning the frame at the top of the call stack.

即返回depth深度調用的棧幀對象.

import sysdef get_cur_info():print sys._getframe().f_code.co_filename # 當前文件名print sys._getframe().f_code.co_name # 當前函數名print sys._getframe().f_lineno # 當前行號print sys._getframe().f_back # 調用者的幀

tail_call_optimized實現尾遞歸優化的原理: 當遞歸函數被該裝飾器修飾后, 遞歸調用在裝飾器while循環內部進行, 每當產生新的遞歸調用棧幀時: f.f_back.f_back.f_code == f.f_code:, 就捕獲當前尾調用函數的參數, 并拋出異常, 從而銷毀遞歸棧并使用捕獲的參數手動調用遞歸函數. 所以遞歸的過程中始終只存在一個棧幀對象, 達到優化的目的。

關于裝飾器的相關知識可以參考這篇博客:
https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014318435599930270c0381a3b44db991cd6d858064ac0000


參考文章:https://blog.csdn.net/jingtiangao/article/details/51554889
https://blog.csdn.net/zcyzsy/article/details/77151709
https://segmentfault.com/a/1190000007641519

總結

以上是生活随笔為你收集整理的知识点讲解八:Python中的尾递归的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。