Recursive function running once more than it should???

31 views
Skip to first unread message

Benjam901

unread,
Apr 2, 2015, 5:06:08 AM4/2/15
to python_in...@googlegroups.com
Hello all,

I am having some trouble with my recursive function, I have written a few for this project and have not seen this behaviour until now.
It is looping over certain xml elements in a file and looking for the correct one based on your selected QTreeWidgetItem which is working fine up to a certain recursion level, I have jumped into the debugger a few times and cannot wrap my head around whats going on.

My issue is when you hit a deeper recursion level as I hit the correct item (if item == treeviewitem[0]) it jumps in and gets the correct XML element which is exactly what I need EXCEPT when it returns it returns to the very bottom gatherXMLElementInfo line and repeats the process even though the process is complete and I dont need it to anymore and is causing program errors.

I was under the assumption that once the function is complete and something is returned the program should finish iterating through the code, it has been this way so far so I am wondering if I am missing something??

Function is below :)

Thanks for the help!

def gatherXMLElementInfo(treeViewItems, root):
#print root.attrib
# Iterate backwards through the object list
for item in reversed(treeViewItems):
# If the current item is the last item in the list
if item == treeViewItems[0]:
#print "Item is", item
# We need to iterate through the parent element children i.e. the list that our element is hiding in
if not item in self.elemsToIgnore:
if root.getchildren():
for elem in root.getchildren():
elemAttributes = elem.attrib
correctElement = [elemAttributes.get(i) for i in elemAttributes if elemAttributes.get(i) == item]
if correctElement:
print correctElement[0]
break
return
else:
return
else:
if item in self.elemsToIgnore:
print "IGNORE", item
xmlElem = root.findall(item)[0]
else:
################# Fix this loop! #############
# Need to get the element from the name of the qt displayed item
for child in root.getchildren():
#print child, root
elemAttributes = child.attrib
correctElement = [elemAttributes.get(i) for i in elemAttributes if elemAttributes.get(i) == item]
if correctElement:
print "FOUNDDDDDD IT", child
xmlElem = child
break
listMinusOne = [i for i in treeViewItems if not i == item]
print " XML ELm", xmlElem
gatherXMLElementInfo(listMinusOne, xmlElem)
print "IGNORE", item
xmlElem = root.findall(item)[0]
else:
################# Fix this loop! #############
# Need to get the element from the name of the qt displayed item
for child in root.getchildren():
#print child, root
elemAttributes = child.attrib
correctElement = [elemAttributes.get(i) for i in elemAttributes if elemAttributes.get(i) == item]
if correctElement:
print "FOUNDDDDDD IT", child
xmlElem = child
break
listMinusOne = [i for i in treeViewItems if not i == item]
print " XML ELm", xmlElem
gatherXMLElementInfo(listMinusOne, xmlElem)

Benjam901

unread,
Apr 2, 2015, 5:09:46 AM4/2/15
to python_in...@googlegroups.com
OOh something weird happened with the gist the actual code without duplicates is below:

def gatherXMLElementInfo(treeViewItems, root):
# Iterate backwards through the object list
for item in reversed(treeViewItems):
# If the current item is the last item in the list
if item == treeViewItems[0]:
# We need to iterate through the parent element children i.e. the list that our element is hiding in
if not item in self.elemsToIgnore:
if root.getchildren():
for elem in root.getchildren():
elemAttributes = elem.attrib
correctElement = [elemAttributes.get(i) for i in elemAttributes if elemAttributes.get(i) == item]
if correctElement:
print correctElement[0]
break
return
else:
return
else:
if item in self.elemsToIgnore:
print "IGNORE", item
xmlElem = root.findall(item)[0]
else:
for child in root.getchildren():
#print child, root
elemAttributes = child.attrib
correctElement = [elemAttributes.get(i) for i in elemAttributes if elemAttributes.get(i) == item]
if correctElement:
print "FOUNDDDDDD IT", child
xmlElem = child
break
listMinusOne = [i for i in treeViewItems if not i == item]
print " XML ELm", xmlElem 
   gatherXMLElementInfo(listMinusOne, xmlElem) 

Marcus Ottosson

unread,
Apr 2, 2015, 5:42:21 AM4/2/15
to python_in...@googlegroups.com
If you manage to distil the issue to a minimal sample, I might be able to take a look; what you've posted so far is a little too much to digest.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/35125785-078f-498b-b796-19566479da4d%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Ben Hearn

unread,
Apr 2, 2015, 5:56:35 AM4/2/15
to python_in...@googlegroups.com
I managed to get it working in the end, it was a very strange behaviour but to fix it I put the recursive function call outside the main loop and set a conditional recall flag which seems to be working ok thus far. I still do not understand why my return statement returned to the function and called it again rather than just saying ok the function is complete lets skip it. I suspect the for loop played some part in it

--
You received this message because you are subscribed to a topic in the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/python_inside_maya/VDbwp3Nd9ec/unsubscribe.
To unsubscribe from this group and all its topics, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOAiNC3%2BLr_Ghf2XM1T0Htx6bmwSPkb2urvw4kExLhQ2zQ%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.



--

Tel - +46 76245 92 90 (Sweden)

Justin Israel

unread,
Apr 2, 2015, 6:27:43 AM4/2/15
to python_in...@googlegroups.com

It looks like you have a bug in your recursion logic. Simply using a return statement during a recursive loop does not automatically stop the entire recursive process. It only returns from that current function, and control returns up to the previous frame on the stack. Control continues to flow from that point so you have to be sure that your recursive loop is set up to properly unwind.

From what I can see in your fixed example, the first thing you do is loop over the reversed tree item list. But I think what happens is at some point you completely filter down the list to empty. You don't check if the list is empty right away and so the for loop doesn't do anything and control reaches that last line which is another recursive call but with a variable that was never defined from the loop. I think if you have first checked if the input list was empty and returned early,  you might have avoided the error.
A tip is that it usually helps to "bail early" instead of nested if statements, when possible. That makes it more clear to read the control flow and know when something isn't going to go any further.

Justin


Reply all
Reply to author
Forward
0 new messages