By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
429,589 Members | 1,194 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 429,589 IT Pros & Developers. It's quick & easy.

Getting out of a recursive function...

P: 3
Hi,

I have a function, looks a bit like this:


def function():
if condition:
do stuff, including a few recursive calls (to function()),
this 'stuff' also changes the state of 'condition'.
'condition' is a global list.
else:
I want to break out of the function and move on

To break out I have tried just sticking a return in the else clause, I've also tried raising an exception (StandardError()) in the else clause and then catching it in an Except outside of the function, then moving on.

However when stepping through in PyWin's debugger, for both the above attempts the function does the 'stuff' successfully, reaches the else clause fine, hits the return, or the exeption is caught fine. But despite this, the program always then jumps back to some of the recursive calls within the if clause.

I just want it to end when it hits the else!

Any help would be much appreciated, I am an obvious newbee, so hopefully this problem has an obvious solution!

I'm running Py2.5 on XPpro, using PyWin to edit and debug. The 'stuff' involves processing some XML, I'm using lxml2.0.1.

Thanks in advance,

Nathan
Mar 25 '08 #1
Share this Question
Share on Google+
6 Replies


jlm699
100+
P: 314
You could do sys.exit(0) as long as you're willing to stop your program completely; however I would assume that's not what you would like to achieve here.
When using recursion it is important to be able to keep track of what you're doing and have an according exit strategy. It would seem to me that you have not set your recursion up properly so it would help in this situation if you could simplify your code as much as possible and give us an example of a tiny snippet of code that still reproduces this error.

P.S. it doesn't sound right to me when you say "a few recursive calls" ... this should be "a recursive call", other wise before each recursive call you will need an if condition: break / return or else you will not have any reliability.
Mar 25 '08 #2

P: 3
Hi, thanks for the quick reply. My code is processing some XML (specifically MathML) which is represented by a lxml doc tree. Here's a piece of my code, with a couple of examples of the recursive calls that seem to be doing me no favours.

Expand|Select|Wrap|Line Numbers
  1. def control():
  2.     if wanted_list:     #if a global list is populated 
  3.         wanted_variable = wanted_list[-1]      
  4.         if wanted_variable in Glob_Vars:    #Glob_Vars is a dictionary, see below 
  5.             wanted_list.remove(wanted_variable)            
  6.             control()      #restart loop with next variable in list
  7.  
  8.         else:            
  9.  
  10.             found_variable = search(wanted_variable)[0]    #finds an instance of variable in the doc tree, called found_variable
  11.             if final_test(found_variable) == True:     #if found_variable is of the form found_variable == 'a constant'                    
  12.                 write_to_Glob_Vars(found_variable)   #write found_variable and its 'constant' value to the Global Dictionary
  13.                 wanted_list.remove(wanted_variable)    #remove from wanted_list as it's value has been found and stored (in Glob_Vars)      
  14.                 replace_all(found_variable)       #replaces all instances of found_variable within the doc tree with it's value as a constant         
  15.                 control()
  16.             else:
  17.                 """more nested if/elses which alter the doc tree and also result in variables being added and subtracted from wanted_list, similar recursive calls to the one above are then made."""
  18.  
  19.     else:
  20.         return     #I wish!
  21.  
As I mentioned before, the doc tree gets processed fine and the final else statement is reached at the correct point ie. when the wanted_list is empty. However when program flow reaches the return call, instead of finishing - as I require - it jumps up to the recursive control() call within the first else clause, and also goes repeatedly to the other recursive calls in the other nested if-elses mentioned.

Hope this is what you wanted to look at, i realise it's a bit bigger than a snippet and it contains quite a few functions i havent defined here!

Cheers again,

Nathan
Mar 26 '08 #3

Expert 100+
P: 849
The issue is that after a recursive call returns, if there is code still to be executed (you didn't call it as part of a return), it will run that code. To get around this, have it return something, say, None, and do each recursive call as return control().
Mar 26 '08 #4

P: 43
Hi, thanks for the quick reply. My code is processing some XML (specifically MathML) which is represented by a lxml doc tree. Here's a piece of my code, with a couple of examples of the recursive calls that seem to be doing me no favours.

Expand|Select|Wrap|Line Numbers
  1. def control():
  2.     if wanted_list:     #if a global list is populated 
  3.         wanted_variable = wanted_list[-1]      
  4.         if wanted_variable in Glob_Vars:    #Glob_Vars is a dictionary, see below 
  5.             wanted_list.remove(wanted_variable)            
  6.             control()      #restart loop with next variable in list
  7.  
  8.         else:            
  9.  
  10.             found_variable = search(wanted_variable)[0]    #finds an instance of variable in the doc tree, called found_variable
  11.             if final_test(found_variable) == True:     #if found_variable is of the form found_variable == 'a constant'                    
  12.                 write_to_Glob_Vars(found_variable)   #write found_variable and its 'constant' value to the Global Dictionary
  13.                 wanted_list.remove(wanted_variable)    #remove from wanted_list as it's value has been found and stored (in Glob_Vars)      
  14.                 replace_all(found_variable)       #replaces all instances of found_variable within the doc tree with it's value as a constant         
  15.                 control()
  16.             else:
  17.                 """more nested if/elses which alter the doc tree and also result in variables being added and subtracted from wanted_list, similar recursive calls to the one above are then made."""
  18.  
  19.     else:
  20.         return     #I wish!
  21.  
As I mentioned before, the doc tree gets processed fine and the final else statement is reached at the correct point ie. when the wanted_list is empty. However when program flow reaches the return call, instead of finishing - as I require - it jumps up to the recursive control() call within the first else clause, and also goes repeatedly to the other recursive calls in the other nested if-elses mentioned.

Hope this is what you wanted to look at, i realise it's a bit bigger than a snippet and it contains quite a few functions i havent defined here!

Cheers again,

Nathan
Try replacing it with a while loop. A while loop will continuously execute all the code inside while the condition is true. Also the keyword break will exit the loop.
Expand|Select|Wrap|Line Numbers
  1. while someCondition:
  2.     # execute some code
  3.  
Mar 26 '08 #5

P: 3
Thanks for all the suggestions.

I replaced the recursive control() calls with return control() and the final else clause with return None. However it still hit the return None then jumped up to some of the return control()s as opposed to fnishing.

Instead, I've put an ugly bodge job in the function that was causing the error, so the unwanted behaviour is still there, but is now harmless. At least for my test cases, which will have to do as I'm short on time.

I've also tried implimenting it in a while loop before, but ran into more stumbling blocks and confused myself!

Cheers again jlm699, Laharl and elcron,

Nathan
Mar 27 '08 #6

P: 2
I think that the function doesn't work that way.. but still,if you find a solution please reply to this message,
thanks!
Jul 18 '19 #7

Post your reply

Sign in to post your reply or Sign up for a free account.