我对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
?
答案 0 :(得分:2)
Python 中的赋值始终以相同的方式工作。它更改=
符号左侧的内容以引用右侧表达式的值。 绝对没有任何"在实现中有所不同"正如你在评论中提出的那样。
有时左侧的项目是容器中的一个插槽(列表,字典,对象)。这些对象是可变的(可以更改),因此您可以更改其插槽引用的内容。当你这样做时,例如:
a = b = [0]
现在a
和b
是同一对象的两个不同名称。如果您执行a[0] = 1
,那么b[0]
也会变为1,因为a
和b
是同一个对象,并且分配不会因为您分配给a
引用的对象中的插槽0;你没有改变a
本身所指的内容。但是,如果您改为a = [1]
,则b[0]
仍为0,因为a
现在指向与b
不同的列表。
这就是你的例子中发生的事情。名称left
和root.left
最初指的是同一个对象。当您将root.left
更改为指向其他对象时,它不会将left
更改为指向同一对象。要做到这一点,left
必须是一个容器,它必须与root
,不 root.left
相同,并且会是什么更改将是left.left
,而不是left
本身。因为除了分配名称之外,您无法以任何方式更改名称的值。