提问人:user6175310 提问时间:7/21/2016 最后编辑:John Kugelmanuser6175310 更新时间:7/21/2016 访问量:192
python 类对象的可变性何时影响赋值?
When does mutability of python class objects affect assignments?
问:
我对 python 对类/对象的可变特性的理解是,如果您进行赋值,那么对原始变量的任何更改也会更改分配的变量/对象。我对下面的这段代码感到困惑。
# 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
答:
2赞
kindall
7/21/2016
#1
Python 中的赋值始终以相同的方式工作。它将符号左侧的事物更改为引用右侧表达式的值。正如您在评论中询问的那样,绝对没有任何“实现不同”。=
有时,左侧的项目是容器中的插槽(列表、字典、对象)。这些对象是可变的(可以更改),因此您可以更改其插槽所引用的内容。当您这样做时,例如:
a = b = [0]
现在和是同一对象的两个不同名称。如果这样做,则也变为 1,因为 和 是同一个对象,并且赋值不会改变这一点,因为您正在赋值给 引用的对象中的插槽 0;你不是在改变它本身所指的东西。但是,如果您改为 ,则保持 0,因为现在指向与 不同的列表。a
b
a[0] = 1
b[0]
a
b
a
a
a = [1]
b[0]
a
b
这就是您的示例中发生的情况。名称和最初引用同一对象。当您更改为指向其他对象时,它不会更改为指向同一对象。要做到这一点,必须是一个容器,并且它必须与 、 和 是同一个容器,并且将要改变的是 ,而不是它本身。因为除了赋值之外,您无法通过任何其他方式更改名称的值。left
root.left
root.left
left
left
root
root.left
left.left
left
评论
0赞
user6175310
7/21/2016
谢谢!所以基本上,如果不是将root.left分配给None,而是对对象进行了一些更改(例如,这将更改为left--->也会变为)这是正确的吗?root.left.left = None
left.left
None
0赞
kindall
7/21/2016
类似的东西。经验法则是,只有当赋值到对象中的某个插槽(例如列表或字典项,或对象属性)时,您才会看到对一个对象的更改反映在另一个对象中,并且只有当另一个引用指向同一包含对象(或父对象, 完成)。
0赞
user6175310
7/25/2016
另一个问题,此时 while 循环中的每次都被分配给 so 并且不再指向同一个树对象,对吧?如果是这种情况,则返回 In End。如何不断更新?无论发生什么,为什么它不等于 ,即为什么不返回?current
current.right
root
current
root
root
current
current
0赞
kindall
7/25/2016
该函数是递归的。处理根节点后,它会调用自己来处理其左右子节点。这些函数调用对其子函数执行相同的操作,依此类推。 永远不会在初始函数中更新,而是递归调用中的不同节点。root
root
评论
test=root
left
left