我最近在一個算法中列出了Sagemath的二叉樹上的生成樹。奇怪的行爲Python生成器的遞歸性
這樣做,我的同事和我發現了一個我們並不完全瞭解的奇怪行爲。
對於規範方面,Sagemath使用Python 2.7和import absolute import from __future__
。
算法使用帶有遞歸調用的「yield」關鍵字逐個列出生成樹。 一次,我們在遞歸調用之前進行測試,以確保它不會觸發錯誤。但是,如果我們刪除測試並讓算法生成一個錯誤,而不捕獲它,那麼生成器不會自行停止,而是會傳遞給下一個遞歸調用。
如果我可以給一本圖文並茂的解釋,讓我們說有一個在每次遞歸調用3個步驟,我們得到了這樣的事情:
- 0級 - 第1步
- 0級 - 第2步
- 級別1 - 步驟1
- 1級 - 第2步
- 2水平 - 步驟1 < - 這裏的錯誤發生,但不停止發電
- 1級 - 第3步
- 2級 - 第1步
- 2級 - 產量 -level 0 - 3步
- ...
如果我們用「try catch」來捕捉錯誤,那麼算法會自行停止。
我讓代碼在這裏;如果你不知道Sagemath,但我不確定你能抓住所有東西,但其中大部分是可以理解的。我會做出具體的評論來突出有趣的部分並刪除代碼的某些部分。
我希望有人能解釋我這種行爲;它就像生成器對象可以在遞歸調用期間處理異常並在生成時忽略它們。
def _rec_spanning_trees():
if len(list_merged_edges) == self.order()-1: # CONDITION TO YIELD
for indexes in product(*list_merged_edges):
yield DiGraph([list_edges[index] for index in indexes], format='list_of_edges', pos=self.get_pos())
# part removed
# THIS HERE !
# "outgoing_edge_iterator" is raising an error if D does not have any edges
s, x, l = D.outgoing_edge_iterator(source).next()
# HERE !
# If I remove the "if(len(...." then the line above will raise an error sometime, but do not if I let it
D.delete_edge(s, x, l)
if len(list(D.depth_first_search(source))) == D.order():
for tree in _rec_spanning_trees():
yield tree
D.add_edge(s, x, l)
# part removed
for tree in _rec_spanning_trees():
yield tree
# part removed
向我們顯示完整的確切錯誤消息。 – user2357112
+您的代碼是如何被調用的 - 所以我們可以重新編寫 – alfasin
@ user2357112這就是要點,沒有錯誤,生成器似乎處理它。 – XanX3601