Breaking out of a recursive function?

Question:

I’m wondering how to break out of a recursive loop to the main function. I am trying to do a simple palindrome exercise. The function should return True for "redivider" but the return True is being passed to is_pal() and the function isn’t breaking. Short of adding a second variable to is_pal to track True/False, what is the proper way to break out of this recursive loop?

def first(word):
    return word[0]

def last(word):
    return word[-1]

def middle(word):
    return word[1:-1]

def is_pal(str):    
    if len(str) == 1: 
        return True

    if first(str) == last(str) and len(str) > 1: 
        is_pal(middle(str))
        
print is_pal("redivider")
Asked By: Chris

||

Answers:

You’re missing a return. Also, don’t use str as a variable name. Last thing, the first and last functions could be named slightly better.

def first_letter(word):
    return word[0]

def last_letter(word):
    return word[-1]

def middle(word):
    return word[1:-1]

def is_pal(word):    
    if len(word) == 1: 
        return True

    if first_letter(word) == last_letter(word) and len(word) > 1:
        return is_pal(middle(word))

print is_pal("redivider")
Answered By: jgritty
def is_pal(str):    
    if len(str) <= 1: 
        return True

    if first(str) == last(str): 
        return is_pal(middle(str))
    else:
        return False

That way, if they don’t match, False is returned; if it makes it all the way to the end, True is returned. I also eliminated a redundant conditional and checked for the edge-case of an even-length palindrome.

Answered By: li.davidm

You need to return False in case they don’t match and add a return statement. Also you will probably want to check against len(str)==0 and len(str)==1:

def is_pal(str):
    if len(str) in [0, 1]:
        return True
    if first(str) == last(str) and len(str) > 1:
        return is_pal(middle(str))
    else :
        return False
Answered By: Qlaus

You don’t "break" out of recursive functions. Trying to do so says you’re thinking about them the wrong way. Currently your recursive call is ignoring the output, which means that the recursion is pointless; whatever is_pal(middle(str)) returns has no effect on the return value of your function.

A recursive algorithm solves the input problem by decomposing the problem into a smaller problem, getting the solution to the smaller problem recursively, and then using the smaller solution to construct a correct solution to the larger problem. You don’t "break" out of the inner calls, you return a solution back up one level. You don’t know (or need to know) whether you’re in an inner call or a top level call. In either case, your function should do the same thing: return True if the argument is a palindrome, and False if it isn’t.

The algorithm you’re trying to implement is basically this:

  1. If the string is of length 1, it’s a palindrome (return True)
  2. Otherwise, if the first character is the same as the last character, then the input is a palindrome if the middle characters are a palindrome.

So what this means is that once you’ve established the first and last characters are the same, the answer to "is my input a palindrome" is exactly the same as the answer to "are the middle characters a palindrome". You need to return that answer to fulfil your contract. So the recursive call should be return is_pal(middle(str)) rather than just is_pal(middle(str)). If this was a top level call, then that’s the answer; if this wasn’t a top-level call, then the outer call is going to need this answer to work out the answer to the outer problem (in this case, by simply returning it).


Btw, your algorithm also has some other problems.

  1. You never return False, so the answer can never be False (in this case you happen to accidentally return None by falling off the end of the function if the first and last character don’t match, and None will probably do as a stand in for False in most cases, but it’s still not really correct).

  2. If the string’s length is zero rather than 1 (which will happen if an empty string is passed in or if a palindrome of even length is passed in once all the pairs of equal first and last characters are stripped off), then you don’t return the correct answer, and in fact you try to get the first and last character of the empty string, which will cause an exception.

Answered By: Ben

One way to break out of a recursive function in Python is to throw an exception and catch that at the top level. Some people will say that this is not the right way to think about recursion, but it gets the job done. Furthermore, if the task is to identify "problem" elements in an array/array of arrays/ndarray etc., a break technique is convenient, because it stops the algorithm from continuing after the global solution has been identified.

def solve_problem(lst):
    def solve_rec(l):
        '''has impl. that may throw an exception '''
    try:
        solve_rec(lst)
        return True
    except:
        return False
Answered By: garde

You can exit the program after printing the results using the exit() function.

That may not be a good practice, but it might be what you’re looking for.

Answered By: sarabjeet

YOU CAN BREAK RECURSION BY RETURNING 1 in ‘if’ statement before you write your ‘function()’ 2nd time.
I mean that’s what we do to find factorial !! RIGHT? 🙂

Answered By: varshil
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.