Python:在函数

时间:2016-09-20 22:55:39

标签: python

Python专家,

我一直在尝试使用Python实现BST,这是我的插入函数代码:

草案1:

def insert(self, val):
    newNode = self._Node(val)

    if (self._root is None):
        self._root = newNode
    else:
        self._insert(self._root,val)

def _insert(self, node, val):

    if node is None:
        node = self._Node(val)

    elif val >= node._val:

        self._insert(node._right, val)
    else:
        self._insert(node._left, val)

但是,除了root之外,我无法构建树。我猜测我通过两个函数传递参数搞砸了,因为当我修改下面的代码时,我明白了:

草案2:

def insert(self, val):
    newNode = self._Node(val)

    if (self._root is None):
        self._root = newNode
    else:
        self._insert(self._root,val)

def _insert(self, node, val):

    if val >= node._val:
        if node._right is None:
                node._right = self._Node(val)
        else:
                self._insert(node._right, val)
    else:
        if node._left is None:
                node._left = self._Node(val)
        else:
                self._insert(node._left, val)

我努力理解为什么草案2有效,但草案1没有。这里有什么帮助?提前谢谢!

2 个答案:

答案 0 :(得分:2)

您的根本误解是变量分配如何工作并与Python的评估策略相互作用:call-by-sharing.

基本上,在您的初稿中,当您执行以下操作时:

def _insert(self, node, val):

    if node is None:
        node = self._Node(val)
    ...

您只是将名称(变量)node分配给self._Node(val)的值,但是当您离开范围时,新对象将被销毁!即使node用于引用方法调用传入的值,简单赋值也不会改变名称引用的对象,而是重新分配名称。< / em>的

然而,在你的第二稿中:

def _insert(self, node, val):

    if val >= node._val:
        if node._right is None:
            node._right = self._Node(val)
        else:
            self._insert(node._right, val)

正在改变一个对象,即:`node._right = self._Node(val)

这是一个简单的例子,希望有启发性:

>>> def only_assign(object):
...   x = 3
...   object = x
... 
>>> def mutate(object):
...   object.attribute = 3
... 
>>> class A:
...   pass
... 
>>> a = A()
>>> a
<__main__.A object at 0x7f54c3e256a0>
>>> only_assign(a)
>>> a
<__main__.A object at 0x7f54c3e256a0>
>>> mutate(a)
>>> a.attribute
3

答案 1 :(得分:1)

我相信这是因为这样做:

node = self._Node(val) 
在_insert函数中

,您不是更改左/右节点的值,而是将名称节点绑定到新的_Node对象,从而使左/右节点为None。

在您的第二个草稿中,您实际上正在影响左/右节点的新对象。

这是一个简单的例子来说明您的代码会发生什么。

猜猜打印(测试)会显示什么?

test = [5, 5, 5]

def function(list):
   list[0] = 10
   list = range(1, 3)

function(test)
print test

如果你认为它会显示[1,2]你错了..它实际上会显示[10,5,5]因为当做list = range(1,3)时我们将名字列表绑定到另一个对象,而不是更改它绑定的第一个对象(一个测试实际上绑定到)