列表添加与之间的区别list append,并在python中列出变量范围

时间:2017-02-14 04:42:59

标签: python python-2.7 tree

我正在解决LeetCode问题(link - click here)。基本上,问题是在给定的二叉树中找到所有路径。

考虑使用二叉树。

   1
 /   \
2     3
 \
  5

我的工作解决方案如下 -

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def binaryTreePaths(self, root):
        """
        :type root: TreeNode
        :rtype: List[str]
        """
        res = []
        self.dfs(root, [], res)
        a = []
        for path in res:
            a.append('->'.join([str(i) for i in path]))
        return a

    def dfs(self, root, ls, res):
        if root == None:
            return

        ls = ls + [root.val]
        if not root.left and not root.right: # if it is a leaf
            res.append(ls)
        if root.left:
            self.dfs(root.left, ls, res)
        if root.right:
            self.dfs(root.right, ls, res)

上面提到的代码效果很好。但是有以下微妙的要点

  • 如果我在调用ls = ls + [root.val]后将ls.append(root.val)更改为res binaryTreePaths,则dfs变为[[],[]]    dfs
  • 在上面提到的相同情况下,在函数[[1,2,5],[1,3]]中,我得到[[1,3],[1,3]]而不是获得res    价值TextView

这到底发生了什么?

2 个答案:

答案 0 :(得分:1)

这是你的实现 - 没有不必要的类 - :

def dfs(root, ls, res):
    if root == None:
        return
    ls = ls + [root.val]
    if not root.left and not root.right:
        res.append(ls)
    if root.left:
        dfs(root.left, ls, res)
    if root.right:
        dfs(root.right, ls, res)

这是输出

In [1]: tree = Node(1, Node(2, None, Node(5)), Node(3))

In [2]: res = []

In [3]: dfs(tree, [], res)

In [4]: res
Out[4]: [[1, 2, 5], [1, 3]]

大!有用。这是.append

def dfs(root, ls, res):
    if root == None:
        return
    ls.append(root.val)
    if not root.left and not root.right:
        res.append(ls)
    if root.left:
        dfs(root.left, ls, res)
    if root.right:
        dfs(root.right, ls, res)

现在,这次......

In [7]: res = []

In [8]: dfs(tree, [], res)

In [9]: res
Out[9]: [[1, 2, 5, 3], [1, 2, 5, 3]]

不太好。请注意,两个列表共享所有内容......它几乎就像是相同的列表一样

In [10]: [hex(id(r)) for r in res]
Out[10]: ['0x104285e88', '0x104285e88']

啊哈!他们相同的列表!

第一个实现的原因是因为以下行:

ls + [root.val]

使成为新列表(这就是为什么你必须将其重新分配给ls),而:

ls.append(root.val)

就地改变列表

In [20]: print(hex(id(x)))
0x104216288

In [21]: x.append(4)

In [22]: x
Out[22]: [1, 2, 3, 4]

In [23]: print(hex(id(x)))
0x104216288

但是看看当我们使用+运算符时会发生什么:

In [24]: x = [1, 2, 3]

In [25]: print(hex(id(x)))
0x1042c8308

In [26]: x = x + [4]

In [27]: print(hex(id(x)))
0x104222588

如果我们先复制列表,我们可以使用append

In [29]: def dfs(root, ls, res):
    ...:     if root == None:
    ...:         return
    ...:     copy = ls[:]
    ...:     copy.append(root.val)
    ...:     if not root.left and not root.right:
    ...:         res.append(copy)
    ...:     if root.left:
    ...:         dfs(root.left, copy, res)
    ...:     if root.right:
    ...:         dfs(root.right, copy, res)
    ...:

In [30]:

In [30]: res = []

In [31]: dfs(tree, [], res)

In [32]: res
Out[32]: [[1, 2, 5], [1, 3]]

为了完整起见,使用扩充赋值运算符,例如some_list += another_list就地修改了列表,基本上等同于some_list.extend(another_list)

In [38]: x = [1, 2, 3, 4]

In [39]: print(hex(id(x)))
0x1045e5d08

In [40]: x += [5]

In [41]: x
Out[41]: [1, 2, 3, 4, 5]

In [42]: print(hex(id(x)))
0x1045e5d08

答案 1 :(得分:0)

根据代码,ls属于None类型,实际上不存在,因为您正在初始化它,因此它会给出.append不存在的错误。 ls = ls + [root.val]等于ls = [root.val]。因此它有效。

希望这有帮助! :)