python类对象的可变性何时影响赋值?

时间:2016-07-20 18:57:00

标签: python class object mutable

我对python的类/对象的可变特性的理解是,如果你做了一个赋值,那么对原始的任何改变都会改变指定的变量/对象。我对此piece of code below感到困惑。

# Recursive solution to Flatten Binary Tree to Linked List by LeetCode

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

class Solution:
    # @param root, a tree node
    # @return root, a tree node
    def flattenHelper(self, root):
        if root == None:
            return None
        else:
            left = root.left
            right = root.right
            root.left = None    # Truncate the left subtree
            current = root

            # Flatten the left subtree
            current.right = self.flattenHelper(left)
            while current.right != None:    current = current.right

            # Flatten the right subtree
            current.right = self.flattenHelper(right)
            return root

    # @param root, a tree node
    # @return nothing, do it in place
    def flatten(self, root):
        self.flattenHelper(root)
        return

问题:一旦left执行,变量None怎么不会自动设置为root.left = None

1 个答案:

答案 0 :(得分:2)

Python 中的赋值始终以相同的方式工作。它更改=符号左侧的内容以引用右侧表达式的值。 绝对没有任何"在实现中有所不同"正如你在评论中提出的那样。

有时左侧的项目是容器中的一个插槽(列表,字典,对象)。这些对象是可变的(可以更改),因此您可以更改其插槽引用的内容。当你这样做时,例如:

a = b = [0]

现在ab是同一对象的两个不同名称。如果您执行a[0] = 1,那么b[0]也会变为1,因为ab是同一个对象,并且分配不会因为您分配给a引用的对象中的插槽0;你没有改变a本身所指的内容。但是,如果您改为a = [1],则b[0]仍为0,因为a现在指向与b不同的列表。

这就是你的例子中发生的事情。名称leftroot.left最初指的是同一个对象。当您将root.left更改为指向其他对象时,它不会将left更改为指向同一对象。要做到这一点,left必须是一个容器,它必须与root root.left相同,并且会是什么更改将是left.left,而不是left本身。因为除了分配名称之外,您无法以任何方式更改名称的值。