2010-09-02 68 views
10

我已經寫了一個小片段,計算給定節點的路徑長度遞歸函數的奇怪的行爲(例如其到根節點的距離):的Python:與關鍵字參數

def node_depth(node, depth=0, colored_nodes=set()): 
    """ 
    Return the length of the path in the parse tree from C{node}'s position 
    up to the root node. Effectively tests if C{node} is inside a circle 
    and, if so, returns -1. 

    """ 
    if node.mother is None: 
     return depth 
    mother = node.mother 
    if mother.id in colored_nodes: 
     return -1 
    colored_nodes.add(node.id) 
    return node_depth(mother, depth + 1, colored_nodes) 

現在有一這個函數發生奇怪的事情(至少對我來說很奇怪):第一次調用node_depth返回正確的值。但是,使用同一個節點第二次調用它將返回-1。設置colored_nodes是在第一次調用空的,但包含了所有節點的ID在已經在第一個添加了第二個電話:

print node_depth(node) # --> 9 
# initially colored nodes --> set([]) 
print node_depth(node) # --> -1 
# initially colored nodes --> set([1, 2, 3, 38, 39, 21, 22, 23, 24]) 

print node_depth(node, colored_nodes=set()) # --> 9 
print node_depth(node, colored_nodes=set()) # --> 9 

我在這裏缺少一些具體的Python的事情,這是真的要是這樣嗎?

由於提前,

耶拿

+0

同樣的事情咬我,我發現你的問題和另一個細節解釋。 http://stackoverflow.com/questions/1132941/least-astonishment-in-python-which-scope-is-the-mutable-default-argument-in – Yefei 2014-06-16 06:50:37

回答

15

「默認值」在Python中的函數參數的函數聲明時被實例化,而不是每次函數被調用。你很少想要改變參數的默認值,所以對默認值使用不可變的東西通常是一個好主意。

在你的情況,你可能想要做這樣的事情:

def node_depth(node, depth=0, colored_nodes=None): 
    ... 
    if colored_nodes is None: colored_nodes = set() 
+0

這是一件很好的事情要知道 - 非常感謝。 (因爲有人問:不,這不是作業。) – jena 2010-09-02 23:44:08

+0

感謝您的支持!偉大的提示。 @jena:謝謝你也問這個。 :) – hayavuk 2010-12-31 12:43:21

6

這是因爲在Python,默認參數值是每個函數被調用一次評估,但只有一次在函數定義時間。如此有效地,您在定義之後,除了第一次呼叫之外,預設填充的colored_nodes將調用該函數。

+0

謝謝,我學到了一些東西。現在我的一天已經完成了。 – wheaties 2010-09-02 23:44:57

相關問題