Python:带关键字参数的递归函数异常行为

9 投票
2 回答
2526 浏览
提问于 2025-04-16 03:39

我写了一个小代码段,用来计算给定节点的路径长度(比如说,它到根节点的距离):

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特有的东西,这真的是应该这样吗?

提前谢谢你,

Jena

2 个回答

6

这是因为在Python中,默认参数的值并不是每次调用函数时都重新计算,而是在定义函数的时候只计算一次。所以实际上,在函数定义后第一次调用以外的每次调用,你都是在用一个已经填好的colored_nodes集合来调用这个函数。

15

在Python中,函数参数的“默认值”是在你定义函数的时候就确定下来的,而不是每次调用这个函数时都重新设置。你通常不想改变参数的默认值,所以用一些不可变的东西作为默认值是个不错的主意。

在你的情况下,你可能想这样做:

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

撰写回答