[英]Python, Make an iterative function into a recursive function
我創建了一個迭代函數,輸出4 3 2 1 0 1 2 3 4。
def bounce2(n):
s = n
for i in range(n):
print(n)
n = n-1
if n <= 0:
for i in range(s+1):
print(-n)
n = n-1
return
bounce2(4)
如果我想要一個完全相同的遞歸函數,我該怎么想?
嘗試這個:
def bounce(n):
if n >= 0:
print(n)
bounce(n - 1)
if n:
print(n)
bounce(4)
輸出將是:4 3 2 1 0 1 2 3 4
預期產量:
4 3 2 1 0 1 2 3 4
讓我把它放到一個圖表中:
4
3
2
1
0
1
2
3
4
我們把它放到代碼中:
def bounce(n):
print(n)
if n:
bounce(n - 1)
print(n)
或者我可以將其視為樹遍歷 - 向下和向上(在這種情況下,樹是非常線性的):
↓
4
↓ | ↑
3
↓ | ↑
2
↓ | ↑
1
↓ | ↑
0
有多種方法可以進行樹遍歷 ,我會在這里選擇DFS - 深度優先搜索 。
DFS偽代碼:
procedure DFS(G,v):
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
if vertex w is not labeled as discovered then
recursively call DFS(G,w)
實際上它是專為圖形設計的,而不僅僅是樹木; 對於樹木,我們不必做“被發現的標簽”部分。
將此DFS轉換為Python:
def dfs(node):
for child_node in node:
dfs(child_node)
在4 3 2 1 0
情況下,我們不需要for
becase,只有n > 0
只有一個或零個子節點 - n - 1
:
def our_dfs(n):
if n > 0:
child_node = n - 1
our_dfs(child_node)
但這只是遍歷而沒有真正有用的東西。 讓我們注入“業務邏輯”:
def bounce(n):
# stuff that happens before we go down
print(n)
# descend
if n > 0:
child_node = n - 1
bounce(child_node)
# stuff that happens after we are back from processing the subtree
if n > 0:
print(n)
因為我們相信良好的工藝,我們想要生成干凈的代碼(好吧我現在開始開玩笑)我們想要只做一件事的函數 - 一個函數用於DFS,一個函數代表我們的樹,單獨的函數用於我們的業務邏輯:
def dfs(node, child_factory, before_stuff, after_stuff):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node, child_factory, before_stuff, after_stuff)
after_stuff(node)
def get_child_nodes(n):
if n:
yield n - 1
def print_before(node):
print(node)
def print_after(node):
if node:
print(node)
def bounce(n):
dfs(n, get_child_nodes, print_before, print_after)
bounce(4)
也許我們可以通過使用嵌套函數使dfs
函數更簡單:
def dfs(node, child_factory, before_stuff, after_stuff):
def f(node):
before_stuff(node)
for child_node in get_child_nodes(node):
f(child_node)
after_stuff(node)
f(node)
嘿,看看它,我還有一個想法......我們可以將它修改為一個函數,它返回一個可以執行DFS的函數( 閉包 ):
def make_dfs(child_factory, before_stuff, after_stuff):
def dfs(node):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node)
after_stuff(node)
return dfs
所以反彈計划現在變成:
def get_child_nodes(n):
if n:
yield n - 1
def print_before(node):
print(node)
def print_after(node):
if node:
print(node)
def make_dfs(child_factory, before_stuff, after_stuff):
def dfs(node):
before_stuff(node)
for child_node in get_child_nodes(node):
dfs(child_node)
after_stuff(node)
return dfs
bounce = make_dfs(get_child_nodes, print_before, print_after)
bounce(4)
那么,這個解決方案有什么好處呢? (注意:仍在開玩笑,部分)你知道,Python有一個遞歸限制 。 有多少函數調用可以嵌套,這個數字非常低。 使用遞歸函數處理未知輸入是一個很大的缺點(有時甚至是安全問題)。 所以現在怎么辦? 好吧,只需用基於堆棧的東西替換make_dfs
的實現(參見DFS Wikipedia頁面)而不是遞歸。 完成。 你不必觸摸任何其他東西。
@ mehrdad-pedramfar發表了一個很好的答案。 你也可以試試這個更精致的:
def my_recursion(current_value, first_portion):
if current_value == 5:
return
print(current_value)
if current_value == 0 or not first_portion:
my_recursion(current_value + 1, False)
elif first_portion:
my_recursion(current_value - 1, True)
my_recursion(4, True)
基本上與第一個相同。 輸出是不同的 - 你會得到雙倍的0.只是為了表明你可以在遞歸調用之前和之后打印。
def bounce(n):
if n >= 0:
print(n)
bounce(n - 1)
print(n)
3 2 1 0 0 1 2 3
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.