代碼很簡單,但它回傳“無”,我不知道為什么。有人可以更正我的代碼嗎?
編輯:編程新手,這是遞回章節末尾的問題。請不要投反對票。
def rev(x):
global y
if len(x)==0:
return y
else:
y=y [x[-1]]
x.pop(-1) #Remove last item from list
rev(x)
z=[1,2,3]
y=[]
print(rev(z))
uj5u.com熱心網友回復:
謝謝,但我應該使用遞回......
遞回是一種函式式遺產,因此以函式式風格使用它會產生最好的結果。這意味著避免諸如突變、變數重新分配和其他副作用之類的事情。
- 如果輸入
t為空,則回傳空結果 - (inductive)
t至少有一個元素。將子問題的結果添加rev(t[1:0)到第一個元素的單例串列中,[t[0]]
def rev(t):
if not t:
return [] # 1. empty t
else:
rev(t[1:]) [t[0]] # 2. at least one element
對于相同的輸入,沒有副作用的函式將始終回傳相同的結果。這使我們可以替換其輸出并對其進行函式呼叫,并輕松可視化其計算程序 -
rev([1,2,3,4,5])
== rev([2,3,4,5]) [1]
== rev([3,4,5]) [2] [1]
== rev([4,5]) [3] [2] [1]
== rev([5]) [4] [3] [2] [1]
== rev([]) [5] [4] [3] [2] [1]
== [] [5] [4] [3] [2] [1]
== [5] [4] [3] [2] [1]
== [5,4] [3] [2] [1]
== [5,4,3] [2] [1]
== [5,4,3,2] [1]
== [5,4,3,2,1]
注意待處理計算的金字塔形狀。隨著輸入的增加,等待合并的單例串列的數量也會增加。如果t非常大,這將導致堆疊溢位。
讓我們看看一個小小的調整如何對這個程序產生巨大的影響——
def rev(t, r = []):
if not t:
return r # 1. empty t, return r
else:
rev(t[1:], [t[0]] r) # 2. at least one element, prepend to r
我們沒有留下待處理的計算供我們回傳,而是引入具有默認值的第二個引數。請注意下面的可視化程序如何保持線性和平坦,而不是像金字塔一樣增長 -
rev([1,2,3,4,5])
== rev([2,3,4,5], [1])
== rev([3,4,5], [2,1])
== rev([4,5], [3,2,1])
== rev([5], [4,3,2,1])
== rev([], [5,4,3,2,1])
== [5,4,3,2,1]
當遞回呼叫是函式的最后一次呼叫時,稱為尾遞回。由于遞回是函式式語言的自然回圈機制,編譯器會檢測到這些尾呼叫并有效防止堆疊增長,稱為尾呼叫消除。
myinput = "abcdefghijklmnopqrstuvwxyz"
print("".join(rev(myinput)))
print("".join(rev(myinput * 100)))
zyxwvutsrqponmlkjihgfedcba
RecursionError: maximum recursion depth exceeded
那么為什么 Python 無法計算rev(myinput * 100)呢?盡管 Python 支持許多函式特性,例如模塊和一流函式,但它不提供尾呼叫消除rev功能,因此我們上面的函式仍然會溢位堆疊。結合其相對較小的堆疊大小,這一事實使 Python 成為一種非常棒的語言,可以實際學習遞回。在了解其局限性后,您將了解撰寫高效演算法意味著什么,甚至了解堆疊安全的無限遞回在其他語言中是如何實作的。
例如,這是一種通過使用 Python 的inspect模塊實作無限遞回的技術,該模塊允許我們比較堆疊幀資料。遞回函式轉換為while回圈,當不再檢測到尾呼叫時,回傳最終結果。Reza Bagheri 在本文中詳細解釋了這種技術-
# tail_rec.py
import inspect
def tail_rec(func):
is_rec = False
t = []
def loop(*args):
nonlocal is_rec
nonlocal t
f = inspect.currentframe()
if f.f_back:
if f.f_back.f_back:
if f.f_code == f.f_back.f_back.f_code:
is_rec = True
t = args
return
while True:
try:
result = func(*args)
except TypeError:
raise Exception("function is not tail-recursive")
if is_rec:
is_rec = False
args = t
else:
return result
return loop
為了啟用優化,我們只需將tail_rec裝飾器添加到我們的函式中 -
from tail_rec import tail_rec # <- import
@tail_rec # <- enable tail call elimination
def rev(t, r = []):
if not t:
return r
else:
return rev(t[1:], [t[0]] r)
突然間,Python 遞回限制消失了——
myinput = "abcdefghijklmnopqrstuvwxyz"
print("".join(rev(myinput * 100)))
zyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcbazyxwvutsrqponmlkjihgfedcba
uj5u.com熱心網友回復:
下面是一個示例,說明如何在不進行切片或遞回的情況下原位反轉串列的內容(并不是您想這樣做):
def rev(x):
i = 0
j = len(x)
while (j := j - 1) > i:
x[i], x[j] = x[j], x[i]
i = 1
return x
print(rev([1,2,3,4,5]))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/391150.html
上一篇:無法翻譯自定義Linq方法
下一篇:C 中的遞回函式呼叫
