2010-09-02 54 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