Getting out of a recursive function...

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • nathanM
    New Member
    • Mar 2008
    • 3

    Getting out of a recursive function...

    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
  • jlm699
    Contributor
    • Jul 2007
    • 314

    #2
    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.

    Comment

    • nathanM
      New Member
      • Mar 2008
      • 3

      #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.

      [CODE=python]
      def control():
      if wanted_list: #if a global list is populated
      wanted_variable = wanted_list[-1]
      if wanted_variable in Glob_Vars: #Glob_Vars is a dictionary, see below
      wanted_list.rem ove(wanted_vari able)
      control() #restart loop with next variable in list

      else:

      found_variable = search(wanted_v ariable)[0] #finds an instance of variable in the doc tree, called found_variable
      if final_test(foun d_variable) == True: #if found_variable is of the form found_variable == 'a constant'
      write_to_Glob_V ars(found_varia ble) #write found_variable and its 'constant' value to the Global Dictionary
      wanted_list.rem ove(wanted_vari able) #remove from wanted_list as it's value has been found and stored (in Glob_Vars)
      replace_all(fou nd_variable) #replaces all instances of found_variable within the doc tree with it's value as a constant
      control()
      else:
      """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."""

      else:
      return #I wish!
      [/CODE]

      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

      Comment

      • Laharl
        Recognized Expert Contributor
        • Sep 2007
        • 849

        #4
        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().

        Comment

        • elcron
          New Member
          • Sep 2007
          • 43

          #5
          Originally posted by nathanM
          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.

          [CODE=python]
          def control():
          if wanted_list: #if a global list is populated
          wanted_variable = wanted_list[-1]
          if wanted_variable in Glob_Vars: #Glob_Vars is a dictionary, see below
          wanted_list.rem ove(wanted_vari able)
          control() #restart loop with next variable in list

          else:

          found_variable = search(wanted_v ariable)[0] #finds an instance of variable in the doc tree, called found_variable
          if final_test(foun d_variable) == True: #if found_variable is of the form found_variable == 'a constant'
          write_to_Glob_V ars(found_varia ble) #write found_variable and its 'constant' value to the Global Dictionary
          wanted_list.rem ove(wanted_vari able) #remove from wanted_list as it's value has been found and stored (in Glob_Vars)
          replace_all(fou nd_variable) #replaces all instances of found_variable within the doc tree with it's value as a constant
          control()
          else:
          """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."""

          else:
          return #I wish!
          [/CODE]

          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.
          [CODE=python]
          while someCondition:
          # execute some code
          [/CODE]

          Comment

          • nathanM
            New Member
            • Mar 2008
            • 3

            #6
            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

            Comment

            • swaroop11
              New Member
              • Jul 2019
              • 2

              #7
              hey nathan! i have the same question,

              I think that the function doesn't work that way.. but still,if you find a solution please reply to this message,
              thanks!

              Comment

              Working...