I've created a general tree in python, by creating a Node object. Each node can have either 0, 1, or 2 trees.
I'm trying to create a method to print a list of all the nodes in a tree. The list need not be in order. Here's my simplistic attempt:
def allChildren(self, l = list()):
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
The first time I run this method, it works correctly. However, for some reason it is storing the previous runs. The second time I run the method, it prints all the nodes twice. Even if I create 2 separate trees, it still remembers the previous runs. E.g: I create 2 trees, a and b. If I run a.allChildren() I receive the correct result. Then I run b.allChildren() and recieve all of a's nodes and all of b's nodes.
You have a mutable value as the default value of your function parameter l. In Python, this means that when you call l.append(self), you are permanently modifying the default parameter.
In order to avoid this problem, set l to a new list every time the function is called, if no list is passed in:
def allChildren(self, l = None):
if l is None:
l = list()
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
This phenomenon is explained much more thoroughly in this question.
try this:
def allChildren(self, l = None):
if(l==None):
l = list()
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
And check out this answer for explanation.
If you're writing default parameter like l = list(), it will create list when compiling function, so it will one instance of list for all function calls. To prevent this, use None and create new list inside the function:
def allChildren(self, l = None):
if not l: l = []
l.append(self)
for child in self.children:
l = child.allChildren(l)
return l
Related
I'm trying to write a function to build a flattened tree of generators based on a list. So if I have a list of items, I want to start with an empty generator, and call a function on the first item and the empty generator, and call the function on the second item and the output of the first function call, and then call the function on the third item and the output of the second function call, and so on. Importantly, I don't want to actually evaluate anything until next is called on the final generator!
So, if the function we're calling on the list and generators is called foo, (and it outputs a generator too, obviously), and the list of items is list...
Right now, what I have is a prototype that looks like this:
>>> tree = iter([{}])
>>> tree = chain.from_iterable((foo(list[0], p) for p in tree))
>>> tree = chain.from_iterable((foo(list[1], p) for p in tree))
>>> tree = chain.from_iterable((foo(list[2], p) for p in tree))
>>> list(tree)
That actually works. It evaluates everything correctly and most importantly doesn't evaluate anything unnecessarily (the lines that begin with an integer are logs printed out when something is actually:
>>> next(tree)
Called on 0
Called on 1
Called on 2
Result A
>>> next(tree)
Called on 1
Called on 2
Result B
UNFORTUNATELY, when I try to use a loop to get this to work on a tail with an arbitrary length:
tree = iter([{}])
for item in list:
tree = chain.from_iterable((foo(item, p) for p in tree))
It doesn't work. Instead, the tree variable is set to the result of foo called on an empty possibility, as if it was the only thing evaluated! I have no idea what's happening, although I have a hunch that its because there is a pointer or something.
Any help would be appreciated!
The call for recursion is clear here:
import itertools as it
def lazy_reduce(list_, tree_base, i=None):
if i is None:
i = len(list_)
if i < 0:
return iter(tree_base)
return it.chain.from_iterable(
foo(list_[i], p)
for p in lazy_reduce(list_, tree_base, i - 1)
)
To avoid the problem with generator scope you can make a function that will have its own scope:
def add_item(tree, item):
return chain.from_iterable((foo(item, p) for p in tree))
tree = iter([{}])
for item in list:
tree = add_item(tree, item)
I'm a new python learner. and there is a question confusing me a lot cause it really waste much time to think about.
There is a algorithm puzzle about binary tree, and a sum, you should find all root-to-leaf paths where each path's sum equals the given sum.
For example:
Given the below binary tree and sum = 22
An example picture here
I have written a python recursive method like blew and it runs correctly on online judgment.
#definition for a binary tree node.
class TreeNode(object):
def __init__(self, x):
self.val=x
self.left=None
self.right=None
class Solution(object):
def pathSum(self, root, sum):
"""
:type root: TreeNode
:type sum: int
:rtype: List[List[int]]
"""
res=[]
if not root:
return res
temp=[root.val]
self.helper(root,sum,res,temp)
return res
def helper(self, root, sum, res, temp):
if not root:
return 0
if root.left==None and root.right==None and sum==root.val:
res.append(temp)
if root.left!=None:
self.helper(root.left,sum-root.val,res,temp+[root.left.val])
if root.right!=None:
self.helper(root.right,sum-root.val,res,temp+[root.right.val])
in the last four lines, I invoke the helper function recursively to find the path sum by pass root left child and root right child.
However, if i rewrite the code like below, I mean only last four lines
if root.left!=None:
temp+=[root.left.val]
self.helper(root.left,sum-root.val,res,temp)
if root.right!=None:
temp+=[root.right.val]
self.helper(root.right,sum-root.val,res,temp)
it gives me wrong answer and can't pass the online judgment.
Dose anyone know what is the difference between this two kind of ways in pass the parameter to a function in python. or it's any declare and pass problem in my code.
In my view, I can't see any difference. Thanks everyone.help me !
+= alters a list in-place:
>>> def inplace(l):
... l += ['spam']
...
>>> def new_list(l):
... l = l + ['spam']
...
>>> a = ['foo']
>>> inplace(a)
>>> a
['foo', 'spam']
>>> a = ['foo']
>>> new_list(a)
>>> a
['foo']
Your original code passes in a new list each time:
self.helper(root.left,sum-root.val,res,temp+[root.left.val])
but your altered code shares temp across all recursive calls and extends it each time. This matters because by creating a new list you gave the recursive calls for the left branch a new, independent list from the right branch of your recursion. By extending the list with += you now give a larger list to the right branch after processing the left branch.
When you say temp += ... you are modifying temp. But you use it in both the left and right cases.
So you have:
temp = [0]
if root.left is not None:
temp += [1] # Now temp is [0, 1], probably okay
...
if root.right is not None:
temp += [2] # Now temp is [0, 1, 2], not [0, 2]!
The second version is incorrect because you would be updating the temp variable between the left leaf check and the right leaf check
if root.left!=None:
temp+=[root.left.val] # temp updated here
self.helper(root.left,sum-root.val,res,temp)
if root.right!=None:
temp+=[root.right.val] # the updated value could be used here, which is wrong
self.helper(root.right,sum-root.val,res,temp)
I am trying to figure out how I can traverse linked list in Python using Recursion.
I know how to traverse linked-lists using common loops such as:
item_cur = my_linked_list.first
while item_cur is not None:
print(item_cur.item)
item_cur = item_cur.next
I was wondering how I could turn this loop into a recursive step.
Thanks
You could do something like this:
def print_linked_list(item):
# base case
if item == None:
return
# lets print the current node
print(item.item)
# print the next nodes
print_linked_list(item.next)
It looks like your linked list has two kinds of parts. You have list nodes, with next and item attributes, and a wrapper object which has an attribute pointing to a the first node. To recursively print the list, you'll want to have two functions, one to handle the wrapper and a helper function to do the recursive processing of the nodes.
def print_list(linked_list): # Non-recursive outer function. You might want
_print_list_helper(linked_list.first) # to update it to handle empty lists nicely!
def _print_list_helper(node): # Recursive helper function, gets passed a
if node is not None: # "node", rather than the list wrapper object.
print(node.item)
_print_list_helper(node.next) # Base case, when None is passed, does nothing
Try this.
class Node:
def __init__(self,val,nxt):
self.val = val
self.nxt = nxt
def reverse(node):
if not node.nxt:
print node.val
return
reverse(node.nxt)
print node.val
n0 = Node(4,None)
n1 = Node(3,n0)
n2 = Node(2,n1)
n3 = Node(1,n2)
reverse(n3)
I have the following simple code:
class Node:
pass
def make_node(value):
n = Node
n.value = value
return n
if __name__ == '__main__':
list = range(100)
random.shuffle(list)
nodes = []
for i in range(len(list)):
nodes.append(make_node(list[i]))
for n in nodes:
print n.value
Upon printing the value at each of the nodes, they are all identical. It seems that each "new node" i built simply overwrites the value of all of the previous ones. Why are these not being set completely separately, and how can I fix it?
I think you want to call the Node constructor:
n = Node()
Otherwise, the assignment to n.value is the same as assigning to Node.value, which sets an attribute of the class, not the object you wanted to create. By returning the Node class object itself, your nodes list contains a bunch of references to the same Node class object.
I'm really stuck on why the following code block 1 result in output 1 instead of output 2?
Code block 1:
class FruitContainer:
def __init__(self,arr=[]):
self.array = arr
def addTo(self,something):
self.array.append(something)
def __str__(self):
ret = "["
for item in self.array:
ret = "%s%s," % (ret,item)
return "%s]" % ret
arrayOfFruit = ['apple', 'banana', 'pear']
arrayOfFruitContainers = []
while len(arrayOfFruit) > 0:
tempFruit = arrayOfFruit.pop(0)
tempB = FruitContainer()
tempB.addTo(tempFruit)
arrayOfFruitContainers.append(tempB)
for container in arrayOfFruitContainers:
print container
**Output 1 (actual):**
[apple,banana,pear,]
[apple,banana,pear,]
[apple,banana,pear,]
**Output 2 (desired):**
[apple,]
[banana,]
[pear,]
The goal of this code is to iterate through an array and wrap each in a parent object. This is a reduction of my actual code which adds all apples to a bag of apples and so forth. My guess is that, for some reason, it's either using the same object or acting as if the fruit container uses a static array. I have no idea how to fix this.
You should never use a mutable value (like []) for a default argument to a method. The value is computed once, and then used for every invocation. When you use an empty list as a default value, that same list is used every time the method is invoked without the argument, even as the value is modified by previous function calls.
Do this instead:
def __init__(self,arr=None):
self.array = arr or []
Your code has a default argument to initialize the class. The value of the default argument is evaluated once, at compile time, so every instance is initialized with the same list. Change it like so:
def __init__(self, arr=None):
if arr is None:
self.array = []
else:
self.array = arr
I discussed this more fully here: How to define a class in Python
As Ned says, the problem is you are using a list as a default argument. There is more detail here. The solution is to change __init__ function as below:
def __init__(self,arr=None):
if arr is not None:
self.array = arr
else:
self.array = []
A better solution than passing in None — in this particular instance, rather than in general — is to treat the arr parameter to __init__ as an enumerable set of items to pre-initialize the FruitContainer with, rather than an array to use for internal storage:
class FruitContainer:
def __init__(self, arr=()):
self.array = list(arr)
...
This will allow you to pass in other enumerable types to initialize your container, which more advanced Python users will expect to be able to do:
myFruit = ('apple', 'pear') # Pass a tuple
myFruitContainer = FruitContainer(myFruit)
myOtherFruit = file('fruitFile', 'r') # Pass a file
myOtherFruitContainer = FruitContainer(myOtherFruit)
It will also defuse another potential aliasing bug:
myFruit = ['apple', 'pear']
myFruitContainer1 = FruitContainer(myFruit)
myFruitContainer2 = FruitContainer(myFruit)
myFruitContainer1.addTo('banana')
'banana' in str(myFruitContainer2)
With all other implementations on this page, this will return True, because you have accidentally aliased the internal storage of your containers.
Note: This approach is not always the right answer: "if not None" is better in other cases. Just ask yourself: am I passing in a set of objects, or a mutable container? If the class/function I'm passing my objects in to changes the storage I gave it, would that be (a) surprising or (b) desirable? In this case, I would argue that it is (a); thus, the list(...) call is the best solution. If (b), "if not None" would be the right approach.