Python:更改字典树结构中的值

时间:2014-08-08 11:22:12

标签: python dictionary reference tree dereference

我在Python中有一个树结构,其中每个节点都是一个列表[dict,int]。该词汇指向孩子们。叶子是普通的,没有列表来节省内存。现在我想用常数因子缩放每个节点中的整数值。我编写了以下递归函数,它接受根节点和因子:

def scale(node,factor):
    if type(node) != list:
        node *= factor;
    else:
        node[1] *= factor;
        for key in node[0]:
            scale(node[0][key],factor);

我的印象是,由于某些Python引用/解除引用问题,保留节点没有更改。这是真的吗?

3 个答案:

答案 0 :(得分:1)

这句话不符合您的想法:

node *= factor

这只会乘以局部变量node,它不会修改你最初传入的dict值.Int是不可变的,所以没有办法将一个函数传递给函数并让函数修改它-place。

本文详细介绍了名称和值如何在Python中运行:Facts and Myths about Names and Values in Python

BTW:检查类型的最佳方法是(如果必须):

if not isinstance(node, list):

答案 1 :(得分:1)

此代码段解释了为什么叶节点(类型为int)未更新的原因:

def f(x):
    print "got x", x
    x *= 10
    print "set x to", x

>>> n = 123
>>> f(n)
got x 123
set x to 1230
>>> n
123

>>> l=[1]
>>> f(l)
got x [1]
set x to [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
>>> l
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

因此,您可以看到n未更改,因为在函数x中仅更新了局部变量f(x)。但是,列表l已更新,因为它是可变的。

解决此问题的任何简单方法是将叶节点包装在list(或其他可变类型)中并存储(并更新)叶值。然后你可以像这样写scale()

def scale(node,factor):
    if len(node) == 1:   # leaf node is a list containing a single int
        node[0] *= factor;
    else:
        node[1] *= factor;
        for key in node[0]:
            scale(node[0][key],factor)

答案 2 :(得分:0)

由于我不打算更改我的数据结构,所以我必须执行以下操作(在我看来,这是Python糟糕的情况之一):

def scale(node,factor):
    for key in node[0]:
        if type(node[0][key]) != list:
            node[0][key] *= factor;
        else:
            node[0][key][1] *= factor;
            scale(node[0][key],factor);

然后在调用递归之前单独更改root int。幸运的是,在这种情况下可能会有更多的好处,因为没有函数调用离开节点...