Reputation: 55
My understanding of python's mutable feature for classes/objects is that if you make an assignment then any change to the original changes the assigned variable/object as well. I confused about this 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
Question: How come the variable left
does not automatically get set to None
once root.left = None
is executed?
Upvotes: 1
Views: 210
Reputation: 184395
Assignment in Python always works the same way. It changes the thing on the left side of the =
sign to refer to the value of the expression on the right side. There is absolutely nothing whatsoever "different in the implementation" as you ask in a comment.
Sometimes the item on the left side is a slot in a container (a list, a dictionary, an object). These objects are mutable (able to be changed), so you can change what their slots refer to. When you do, for example:
a = b = [0]
Now a
and b
are two different names for the same object. If you do a[0] = 1
then b[0]
also becomes 1, because a
and b
are the same object, and the assignment doesn't change this because you are assigning to slot 0 within the object referenced by a
; you are not changing what a
itself refers to. But if you instead do a = [1]
, then b[0]
remains 0, because a
now points to a different list from b
.
This is what's happening in your example. The names left
and root.left
initially refer to the same object. When you change root.left
to point to a different object, it doesn't change left
to point to the same object. For that to happen, left
would have to be a container, and it would have to be the same container as root
, not root.left
, and what would change would be left.left
, not left
itself. Because you can't change the value of a name by any way other than assigning to it.
Upvotes: 2