I'm trying to write an algorithm in python to print out all paths from the root of a (binary) tree to each leaf. Here's my code:
def fb_problem(node, curr_trav):
curr_trav = curr_trav + [node]
if node.left is None and node.right is None:
for path_node in curr_trav:
print path_node.data
print "XXX"
if node.left is not None:
fb_problem(node.left, curr_trav)
if node.right is not None:
fb_problem(node.right, curr_trav)
fb_problem(root, [])
I keep a list of nodes in the current traversal, and when I've reached a leaf, I print out the list. I'm misunderstanding something about the way python passes objects though. I thought that as each recursive call completes and is popped off the stack, the original curr_trav variable would not be affected by what the recursive call did. However, it seems as if the line
curr_trav += [node]
Is mutating the original list. The += operator returns a new list, as opposed to .append(), which actually mutates the original object. So shouldn't this call just be reassigning the name given to the object in the function, not mutating the original object? When I change the line to something like
t_trav = curr_trav += [node]
Everything works fine, but I don't understand what the problem with the original line was. Please let me know if my question is unclear.
Your understanding of
+=is not quite correct. All operators in Python are really just shortcuts. For example,a + bisa.__add__(b)ifahas an__add__method. Ifadoes not, it isb.__radd__(a). Ifbdoesn't have that method, an error is raised. Usually,a += bbehaves quite likea = a + b, but in the case of mutable objects, it usually doesn't. That is becausea += bisa.__iadd__(b)ifahas the__iadd__method. Ifadoes not, it is the same asa = a.__add__(b). Ifadoesn't have that either, it is the same asa = b.__radd__(a). Since lists do have the__iadd__method, the actual list object is changed instead of redefiningcurr_trav.